最常见的原因是您没有关闭管道的写入端,因此EOF永远不会被发送 . 常见的例子是当您的代码如下所示:
int fds[2];
pipe(fds); // open a pipe
if (fork()) {
// parent process
write(fds[1], ... // write data
close(fds[1]); // close it
} else {
// child process
while (read(fds[0], ....) > 0) {
// read until EOF
这里的问题是管道的写端不会被关闭 - 父进程关闭它,但子进程仍然打开了写描述符 . 因此,孩子永远不会在读取描述符上看到EOF .
在分配子项后,您需要做的第一件事是 close(fds[1]); ,关闭其写入描述符的副本 . 这样,当父级关闭对管道写入端的最后一个剩余引用时,子级将在读取端看到EOF .
Edit
看看你添加的链接,这正是问题 - 孩子仍然在其标准输出上打开管道的写端 . 不要将写入结束复制到子项中的stdout,只需将其关闭即可 . 在其他地方发送stdout(日志文件或/ dev / null)
Edit
对于双向沟通,你需要两个管道:
int tochild[2], fromchild[2];
pipe(tochild); pipe(fromchild);
if (fork()) {
close(tochild[0]);
close(fromchild[1]);
//write to tochild[1] and read from fromchild[0]
} else {
dup2(tochild[0], 0);
dup2(fromchild[1], 1);
close(tochild[0]); close(tochild[1]);
close(fromchild[0]); close(fromchild[1]);
exec(...
}
你需要非常小心地在父母中写入数据 - 但是如果要向孩子发送大量数据,你不能在读取孩子的输出之前发送所有数据,否则你可能会死锁(两个管道都填满了)当子块阻止尝试输出时,父块阻止尝试为子节点写入更多数据 . 您需要使用poll或select来判断何时有要读取的数据或要写入的空间,并且您可能希望将管道(父项至少结束)置于非阻塞模式 .