C:从父到子过程中未检测到管道中的EOF

时间:2017-11-07 13:50:53

标签: c unix process pipe broken-pipe

我参加了一门专注于C的编程课程,目前我们正在通过管道和流程。我已经分配了一个课堂活动,我必须让父母创建一个孩子来打印从父母输入的输入。我可以将程序输入到子输出并输出,但是当我按住Ctrl + D进行EOF时,我仍然可以输入输入(没有输出)。

我试着在纸上遵循我的逻辑,这似乎是正确的,但有些事情是错误的。我试图对我能写的短语进行硬编码以便我可以退出我的孩子,但是当我试图纠正这种情况时,我的管道坏了。

以下是我的2个文件:

newshell.c

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>

int main(void){
    pid_t child1;
    int fd[2];
    char buffer1[100];
    int bytes;

    pipe(fd);
    child1 = fork();

    if (child1 == 0){
        dup2(fd[0],fileno(stdin));
        close(fd[1]);
        printf("You are in the child.\n");
        execlp("./printdata","printdata.c",0);
    }
    else {
        dup2(fd[1],fileno(stdout));
        close(fd[0]);
        while(fgets(buffer1,sizeof(buffer1),stdin) != NULL){
            write(fd[1],buffer1,(strlen(buffer1)+1));
        }
        write(fd[1],"999",sizeof("999"));
        wait(0);
        close(fd[1]);
        close(fd[0]);

        printf("Child ended. You are in the parent.\n");
    }
    return 0;
}

printdata.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void){
    char buffer[100];
    int bytes;
    printf("You're in the new process\n");
    while(bytes = read(fileno(stdin),buffer,sizeof(buffer)) >= 0){
        printf("%s\n",buffer);
        if (strcmp(buffer,"999") == 0){
            return 0;
        }
    }
    printf("Done here\n");
    return 0;
}

这里的逻辑是我在父级中创建一个等待来自父级的输入的子进程。我硬编了一个哨兵&#39; (正如我的教授所说的那样)因为当我输入它时我的EOF没有被检测到。老师接受了我所拥有的,因为大多数人都没有完成任务,但我想知道为什么它不能为自己的利益工作。

谢谢。

2 个答案:

答案 0 :(得分:1)

重点是:当您按CTRL+D时,您会在父母的标准输出上发出EOF信号。 所以父母离开了这个循环

while(fgets(buffer1,sizeof(buffer1),stdin) != NULL)

因为fgets()在EOF上返回NULL

但是现在,您需要关闭fd[1] fileno(stdout)(因为您重复了它并在调用wait(0)之前同时执行了 ),因为关闭最后一个引用该管道的文件描述符将在输入到子进程时发出EOF信号!我有点不清楚你为什么dup2() fd[1]fileno(stdout),也许你应该把它排除在外。

经过这些修改后,它应该按预期工作。

答案 1 :(得分:1)

父母需要在调用wait之前关闭fd[1]。只要任何进程打开管道的写入侧,子进程中的读取就会被阻塞。在您的情况下,父母将写入侧保持打开状态,等待孩子终止。并且孩子在读取时被阻塞,等待父母关闭管道的写入侧。换句话说,写:

 close(fd[1]);
 wait(0);

并且,正如ctx指出的那样,你需要关闭父节点中的stdout,或者停止无意义的dup2