从父进程和子进程关闭管道
Posted
技术标签:
【中文标题】从父进程和子进程关闭管道【英文标题】:close pipe from parent and child process 【发布时间】:2021-07-31 12:05:28 【问题描述】:#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
int p[2];
pipe(p);
if (fork() == 0)
// child
/*#0*/ close(p[1]);
int received = -1;
while (read(p[0], &received, 4) != 0)
printf("receive integer: %d\n", received);
received = -1;
printf("child exit\n");
exit(0);
else
// parent
/*#1*/ close(p[0]);
int sent = 42;
write(p[1], &sent, 4);
/*#2*/ close(p[1]);
printf("wait for child\n");
wait(0);
printf("finished\n");
我试图理解 C 中的 fork
和 pipe
。这个程序派生了一个子进程,它从父进程接收一个整数,然后在管道关闭时退出。执行时,它会打印
wait for child
receive integer: 42
child exit
finished
然而,在close(p[1]);
的位置#0
被移除后,while 循环卡住了:read
将无限等待来自管道的传入变量并且永远不会检测到管道关闭。
有人可以向我解释为什么p[1]
必须由父(位置#2
)和子(位置#0
)进程关闭吗?
【问题讨论】:
因为它是这样工作的。在关闭管道之前,需要关闭管道的所有写入端。系统不会为您检测这种竞争条件;如果您自己被阻止,这是您需要修复的错误。 顺便说一句,您应该将4
替换为sizeof sent
或sizeof received
或sizeof(int)
(最好是前两个)。
【参考方案1】:
这是代码(来自 Linux 手册页),代码底部带有 cmets。 https://man7.org/linux/man-pages/man2/pipe.2.html
在 /#2/close(pipefd[1]) 处,评论指出“读者将看到 EOF”。这意味着不再有任何内容可以读入子进程,然后语句“read(p[0], &received, 4)”将返回 0。在 Linux 手册页中 https://man7.org/linux/man-pages/man2/read.2.html 声明“成功时,返回读取的字节数(零表示文件结束)”
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int
main(int argc, char *argv[])
int pipefd[2];
pid_t cpid;
char buf;
if (argc != 2)
fprintf(stderr, "Usage: %s <string>\n", argv[0]);
exit(EXIT_FAILURE);
if (pipe(pipefd) == -1)
perror("pipe");
exit(EXIT_FAILURE);
cpid = fork();
if (cpid == -1)
perror("fork");
exit(EXIT_FAILURE);
if (cpid == 0) /* Child reads from pipe */
close(pipefd[1]); /* Close unused write end */
while (read(pipefd[0], &buf, 1) > 0)
write(STDOUT_FILENO, &buf, 1);
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
_exit(EXIT_SUCCESS);
else /* Parent writes argv[1] to pipe */
close(pipefd[0]); /* Close unused read end */
write(pipefd[1], argv[1], strlen(argv[1]));
/*#2*/ close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
【讨论】:
以上是关于从父进程和子进程关闭管道的主要内容,如果未能解决你的问题,请参考以下文章
Perl 行为差异关闭由 open() 产生的子进程与 IPC::Open3