UNIX FIFO:如果我不关闭 fifo 的输入端,进程就会挂起
我刚刚开始使用 UNIX FIFO,并且在试验我的第一个 FIFO 程序时发现了一些东西。该程序的工作方式如下:创建 FIFO 后,使用 fork()
函数启动两个进程。子进程通过 FIFO 读取父进程传递给他的内容,并将其打印在屏幕上。交换的数据是指定为参数的字符串。问题是:在父部分中,如果我忘记关闭 FIFO 的输入端(意味着我排除 close(fd)
行),程序就会挂起,即使之间的数据进程已正确交换。否则,一切正常,程序终止而不会挂起。有人可以解释一下为什么吗?
感谢您的耐心等待。下面是main函数的代码:
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("An argument must be specified\n");
return -1;
}
int ret = mkfifo("./fifo.txt", 0644);
char buf;
if(ret < 0)
{
perror("Error creating FIFO");
return -1;
}
pid_t pid = fork();
if(pid < 0)
{
perror("Error creating child process");
return -1;
}
if(pid == 0) /* child */
{
int fd = open("./fifo.txt", O_RDONLY); /* opens the fifo in reading mode */
while(read(fd, &buf, 1) > 0)
{
write(STDOUT_FILENO, &buf, 1);
}
write(STDOUT_FILENO, "\n", 1);
close(fd);
return 0;
}
else /* father */
{
int fd = open("./fifo.txt", O_WRONLY); /* opens the fifo in writing mode */
write(fd, argv[1], strlen(argv[1]));
close(fd);
waitpid(pid, NULL, 0);
return 0;
}
}
I've just started working with UNIX FIFOs, and I discovered something while experimenting with my first FIFO program. The program works this way: after creating the FIFO, two processes are started using the fork()
function. The child process reads what the father passes to him through the FIFO, and prints it on the screen. The data exchanged is the string specified as an argument. The question is: in the father section, if I forget to close the input side of the FIFO (meaning that I exclude the close(fd)
line) the program would just hang, even if the data between the processes is exchanged correctly. Otherwise, everything works fine and the program terminates withouth hanging. Can someone please explain me why?
Thanks for your patience. Here is the code of the main function:
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("An argument must be specified\n");
return -1;
}
int ret = mkfifo("./fifo.txt", 0644);
char buf;
if(ret < 0)
{
perror("Error creating FIFO");
return -1;
}
pid_t pid = fork();
if(pid < 0)
{
perror("Error creating child process");
return -1;
}
if(pid == 0) /* child */
{
int fd = open("./fifo.txt", O_RDONLY); /* opens the fifo in reading mode */
while(read(fd, &buf, 1) > 0)
{
write(STDOUT_FILENO, &buf, 1);
}
write(STDOUT_FILENO, "\n", 1);
close(fd);
return 0;
}
else /* father */
{
int fd = open("./fifo.txt", O_WRONLY); /* opens the fifo in writing mode */
write(fd, argv[1], strlen(argv[1]));
close(fd);
waitpid(pid, NULL, 0);
return 0;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
read(2)
会阻塞,直到有可用字符或另一端关闭通道为止。父进程必须关闭管道才能让最后一个子进程 read() 返回。如果在父进程中省略close(fd)
,子进程将阻塞在read()
中,直到父进程退出(自动关闭管道),但父进程会挂起waitpid()
直到子进程退出。read(2)
blocks until there are characters available or the channel is closed at the other end. The father process must close the pipe in order for the last childread()
to return. If you omit theclose(fd)
in the father, the child will block in theread()
until the father exits (closing the pipe automatically) but father will hang inwaitpid()
until the child exits.首先,您发布的代码存在几个问题。
#include
指令,因此您调用的任何函数的范围内都没有原型。 C89 需要可变参数函数的原型,例如 printf() ; C99 需要所有 函数的原型。 C89 和 C99 都需要在O_RDONLY
、O_WRONLY
、STDOUT_FILENO
和NULL
范围内进行声明。-1
不是main()
允许的返回值。一个小问题:通常的命名法是“父母和孩子”,而不是“父亲和孩子”。
我修改了你的程序来纠正这个问题并提高可读性:
但最重要的是,你没有提到你正在使用什么操作系统和编译器。
我无法重现该问题,并且我怀疑它可能与上面列出的问题之一有关。
First things first: there are several issues with the code you posted.
#include
directives, hence no prototypes in scope for any of the functions you call. C89 requires prototypes for variadic functions such asprintf()
; C99 requires prototypes for all functions. Both C89 and C99 require declarations in scope forO_RDONLY
,O_WRONLY
,STDOUT_FILENO
andNULL
.-1
is not an allowed return value formain()
.A minor nit: the usual nomenclature is "parent and child", not "father and child".
I have modified your program to correct this issue and improve readability:
But most importantly, you did not mention what operating system and compiler you are using.
I am unable to reproduce the issue, and I suspect it may be related to one of the issues listed above.