了解C {/ 1}}和fork()
。
以下代码创建了一个管道和一个子进程。孩子发送一条消息,父母将其阅读。
pipe()
它运作正常。如果你评论int main () {
int fd[2];
pid_t pid;
pipe(fd);
pid = fork();
if (pid == 0) {
// Child
close(fd[0]);
write(fd[1], "HELLO", (strlen("HELLO")+1));
exit(0);
}else{
// Parent
close(fd[1]);
char buffer[80];
read(fd[0], buffer, sizeof(buffer));
printf("Received string: %s", buffer);
}
return 0;
}
行,父母会报告它收到一个带有奇怪字符的字符串,我认为这是正常的,因为它正在读取与我的程序无关的内存。
然而,它带来了一个问题:父母是否有可能在 之前读取管道 ,孩子可以写数据?如果发生了这种情况,它将会读取奇怪的字符。
父母如何等待"从孩子那里写数据?
将来我可能会有几个孩子的过程,我希望父母等待所有孩子完成这些过程。继续他们的工作。
答案 0 :(得分:1)
如果您对写入行进行注释,则父级将报告它收到了带有奇怪字符的字符串
如果在孩子中跳过了对write
的调用,则子进程结束,管子端的子进程结束将被关闭。
父母检测到孩子的管道末端已关闭,这使得对read()
的调用返回。父母实际上没有读任何东西,所以缓冲区保持未初始化状态,"垃圾"打印出来。
请从以下read
's POSIX specification找到relvant部分:
尝试从空管道或FIFO读取时:
- 如果没有进程打开管道进行写入,则read()将返回0以指示文件结束。
[...]
- 如果某个进程打开了管道并且O_NONBLOCK已清除,则read()将阻塞调用线程,直到写入一些数据或管道被管道打开以供写入的所有进程关闭。
要使代码能够处理孩子不写任何内容的情况,请测试父母对“读取()”的调用是否真正读过:
ssize_t result = read(fd[0], buffer, sizeof(buffer));
if (-1 == result) /* Also ALWAYS test for error. */
{
perror("read() failed");
}
else if (0 == result)
{
fprintf(stderr, "read() returned without having read anything.\n")
}
else
{
printf("Received string: '%s'", buffer);
}