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

Kyl*_*son 4 c c++ io fork pipe

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

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

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

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

这是代码:

http://gist.github.com/621210

Chr*_*odd 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
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来判断何时有要读取的数据或要写入的空间,并且您可能希望将管道(父项至少结束)置于非阻塞模式.