最常见的原因是您没有关闭管道的写入端,因此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
Run Code Online (Sandbox Code Playgroud)
这里的问题是管道的写端不会被关闭 - 父进程关闭它,但子进程仍然打开了写描述符.因此,孩子永远不会在读取描述符上看到EOF.
分叉子代后你需要做的第一件事就是close(fds[1]);关闭它的写描述符副本.这样,当父级关闭对管道写入端的最后一个剩余引用时,子级将在读取端看到EOF.
编辑
看看你添加的链接,这正是问题 - 孩子仍然在其标准输出上打开管道的写端.不要将写入结束复制到子项中的stdout,只需将其关闭即可.在其他地方发送stdout(日志文件或/ dev/null)
编辑
对于双向沟通,你需要两个管道:
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(...
}
Run Code Online (Sandbox Code Playgroud)
你需要非常小心地在父母中写入数据 - 但是如果要向孩子发送大量数据,你不能在读取孩子的输出之前发送所有数据,否则你可能会死锁(两个管道都填满了)当子块阻止尝试输出时,父块阻止尝试为子节点写入更多数据.您需要使用poll或select来判断何时有要读取的数据或要写入的空间,并且您可能希望将管道(父项至少结束)置于非阻塞模式.