提问人:Overstacked 提问时间:10/13/2023 最后编辑:OkaOverstacked 更新时间:10/13/2023 访问量:63
当“读取”可以阻止管道中的父进程时,为什么要“等待”子进程?
Why `wait` for the child when `read` could supposedly block the parent process in pipe?
问:
我正在学习进程之间的通信,我看到了以下代码,用于在父进程和子进程之间乒乓球一个字节:pipe
int
main(int argc, char **argv)
{
int p[2];
char buf[2];
char *send = "a", *rec = "b";
pipe(p);
int pid = fork();
if(pid == 0){
if(read(p[0], buf, 1) != 1){
fprintf(2, "child failed to read byte from parent.\n");
exit(1);
};
close(p[0]);
printf("%d: received ping\n",getpid());
if(write(p[1], rec, 1) != 1){
fprintf(2, "child failed to send byte to parent.\n");
exit(1);
};
close(p[1]);
exit(0);
} else if(pid > 0){
if(write(p[1], send, 1) !=1){
fprintf(2, "parent failed to send byte to child.\n");
exit(1);
};
close(p[1]);
wait(0);
if(read(p[0], buf, 1) != 1) {
fprintf(2, "parent failed to read byte back from child.\n");
exit(1);
};
close(p[0]);
printf("%d: received pong\n", getpid());
exit(0);
}
else exit(1);
}
此代码有效。然而,在了解到这一点之后
如果没有可用的数据,则对管道的读取将等待写入数据或所有文件描述符 指要关闭的写入端;在后一种情况下,read 将返回 0,就像 已访问数据文件。
我开始有些怀疑。in 父进程现在似乎是多余的,因为在父进程写入之前,父进程不会运行,这在某种程度上充当了 .wait(0)
read
wait()
因此,我删除了该行,代码仍然可以打印“received pong”,但不再打印“received ping”,这意味着孩子没有按预期执行。这让我很困惑。wait(0)
read
答:
澄清一下:父进程使用等待来等待
任何子进程终止,并释放与之关联的系统信息(通常称为收获僵尸进程)。它的功能仅与写入/读取管道无关,因为它模糊地属于进程间通信的范畴。
如果没有父进程的 and,父进程很可能只是在子进程获得 CPU 时间之前读取它写入管道的字节。毕竟,这两个过程都是对同一管道的读取和写入。在这种情况下,父进程无法通过退出而不等待来正确获取子进程。子进程成为一个孤立进程,因为它将永远阻塞,试图从管道中读取一个字节,因为它仍然打开管道的写入端。wait
write
read
使用 present 时,父进程将一个字节写入管道,然后阻塞等待子进程终止。大约在同一时间,子进程读取一个字节(可能是阻塞),然后写入一个字节,然后终止。子进程终止后,父进程将收获子进程,然后读取一个字节。wait
在适当的情况下,将两根管道留在原处进行双向通信,并更积极地(即尽早)使用每根管道的未使用端。警惕僵局。wait
close
评论