(c / c ++)试图从父进程强制EOF向子进程发送输入

时间:2010-10-11 22:00:05

标签: c++ c io fork pipe

我有一个非常简单的c / c ++程序,它强制子进程执行另一个程序,然后将一些数据发送到该子程序,并等待响应。

子程序从stdin读取并在继续之前等待EOF。

我的问题是,子程序从管道写入接收初始输入,但它从未看到EOF(即使我关闭了管道),所以它会永远等待。

我不确定为什么关闭管道并不意味着孩子的标准输入的EOF?

这是代码:

http://gist.github.com/621210

3 个答案:

答案 0 :(得分:6)

最常见的原因是您没有关闭管道的写入端,因此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。

修改

查看您添加的链接,这正是问题 - 孩子仍然在其标准输出上打开管道的写入结束。不要将写入结束复制到子项中的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(...
}

您需要非常小心地在父级中写入数据,但是 - 如果有大量数据的话 发送给孩子后,你不能在读取孩子的输出之前发送所有内容,否则你可能会死锁(两个管道都填满了,而且当孩子阻止尝试输出时,父块会试图为孩子写更多的数据)。您需要使用poll或select来判断何时有要读取的数据或要写入的空间,并且您可能希望将管道(父项至少结束)置于非阻塞模式。

答案 1 :(得分:3)

更新了我认为的问题: 您正在阅读角色并检查该角色的EOF。这不是read()系统调用的工作原理。在EOF时它将返回0。它不会将EOF写入缓冲区。

我也看到你一次只读一个角色。这是一种读取数据的糟糕方式。它比读取大缓冲区(比如4或8 kB)要快几倍

我相信你在这里也有一个共同的错误。您没有检查write()的返回值。

写入系统调用不保证在返回之前写入所有数据。它可能会写入4000个字节并返回。它将返回写入的字节数。然后,您有责任更新缓冲区指针并再次调用write。

或者它可能会返回错误代码,因此您必须检查错误代码。

答案 2 :(得分:-1)

这是我为你写的概念证明:

Fork exec double pipe by dino ciuffetti