C 到 Python 管道 - 如何检测 reader 访问
C to Python piping - How to detect reader access
我正在使用 C 程序写入命名管道并使用 Python 程序读取它。
如果我停止 Python 程序 (reader),那么编写器就会自行停止,尽管这是在 while(1) 循环中。为什么会这样?是无声的崩溃吗?
第二个问题,如果我想检测reader什么时候断开,我该怎么办。我的理想情况是检测断开连接然后继续空闲(即停止发送任何内容)并在 reader 返回后恢复。
下面的玩具代码。
作家(C):
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int fd;
// FIFO file path
char * myfifo = "/tmp/myfifo";
// Creating the named file(FIFO)
// mkfifo(<pathname>, <permission>)
mkfifo(myfifo, 0666);
char arr1[80];
while (1)
{
// Open FIFO for write only
fd = open(myfifo, O_WRONLY);
// Take an input from user.
fgets(arr1, 80, stdin);
// Write the input on FIFO
// and close it
write(fd, arr1, strlen(arr1)+1);
close(fd);
}
return 0;
}
Reader (Python)
f = open("/tmp/myfifo")
while 1:
print(f.readline(), end = "")
f.close()
当您停止读取程序时,写入程序将在尝试写入管道时收到一个 SIGPIPE
信号。该信号的默认处理是终止进程。
如果要检测此条件,请使用signal()
或sigaction()
将配置更改为SIG_IGN
。然后写入管道会报EPIPE
错误。
此外,您不应该在每次循环时关闭并重新打开管道。开头打开一次,结尾关闭。关闭管道会导致 reader 收到 EOF,之后它将无法读取任何内容。
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
int main()
{
int fd;
// FIFO file path
char * myfifo = "/tmp/myfifo";
// Creating the named file(FIFO)
// mkfifo(<pathname>, <permission>)
mkfifo(myfifo, 0666);
// Open FIFO for write only
fd = open(myfifo, O_WRONLY);
signal(SIGPIPE, SIG_IGN);
char arr1[80];
while (1)
{
// Take an input from user.
fgets(arr1, 80, stdin);
// Write the input on FIFO
// and close it
int res = write(fd, arr1, strlen(arr1)+1);
if (res < 0) {
perror("write");
break;
}
}
close(fd);
return 0;
}
当您停止写入程序时,reader 将在尝试从管道读取时收到 EOF。当 f.readline()
到达 EOF 时,它 returns 是一个空字符串。您的 Python 脚本不会对此进行检查,因此它会无限循环。
将 reader 更改为:
with open("/tmp/myfifo") as f:
while True:
line = f.readline()
if not line:
break
print(line, end = "")
然后循环将在管道关闭时终止。
我正在使用 C 程序写入命名管道并使用 Python 程序读取它。
如果我停止 Python 程序 (reader),那么编写器就会自行停止,尽管这是在 while(1) 循环中。为什么会这样?是无声的崩溃吗?
第二个问题,如果我想检测reader什么时候断开,我该怎么办。我的理想情况是检测断开连接然后继续空闲(即停止发送任何内容)并在 reader 返回后恢复。
下面的玩具代码。
作家(C):
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int fd;
// FIFO file path
char * myfifo = "/tmp/myfifo";
// Creating the named file(FIFO)
// mkfifo(<pathname>, <permission>)
mkfifo(myfifo, 0666);
char arr1[80];
while (1)
{
// Open FIFO for write only
fd = open(myfifo, O_WRONLY);
// Take an input from user.
fgets(arr1, 80, stdin);
// Write the input on FIFO
// and close it
write(fd, arr1, strlen(arr1)+1);
close(fd);
}
return 0;
}
Reader (Python)
f = open("/tmp/myfifo")
while 1:
print(f.readline(), end = "")
f.close()
当您停止读取程序时,写入程序将在尝试写入管道时收到一个 SIGPIPE
信号。该信号的默认处理是终止进程。
如果要检测此条件,请使用signal()
或sigaction()
将配置更改为SIG_IGN
。然后写入管道会报EPIPE
错误。
此外,您不应该在每次循环时关闭并重新打开管道。开头打开一次,结尾关闭。关闭管道会导致 reader 收到 EOF,之后它将无法读取任何内容。
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
int main()
{
int fd;
// FIFO file path
char * myfifo = "/tmp/myfifo";
// Creating the named file(FIFO)
// mkfifo(<pathname>, <permission>)
mkfifo(myfifo, 0666);
// Open FIFO for write only
fd = open(myfifo, O_WRONLY);
signal(SIGPIPE, SIG_IGN);
char arr1[80];
while (1)
{
// Take an input from user.
fgets(arr1, 80, stdin);
// Write the input on FIFO
// and close it
int res = write(fd, arr1, strlen(arr1)+1);
if (res < 0) {
perror("write");
break;
}
}
close(fd);
return 0;
}
当您停止写入程序时,reader 将在尝试从管道读取时收到 EOF。当 f.readline()
到达 EOF 时,它 returns 是一个空字符串。您的 Python 脚本不会对此进行检查,因此它会无限循环。
将 reader 更改为:
with open("/tmp/myfifo") as f:
while True:
line = f.readline()
if not line:
break
print(line, end = "")
然后循环将在管道关闭时终止。