退出父进程后,subprocess无法读取

通过函数execvp()分支并执行子程序后,父进程退出。 但是,这会导致subprocess中的函数fgets()立即返回而不等待来自stdin

我想父进程的退出将发送一些信号到subprocess,使fgets()函数返回。 有人能为我解释吗?

儿童节目代码:

 /* cc child.c -o child */ int main () { char buffer[10]; fgets(buffer, 10, stdin); printf("This is what child program read:\n%s", buffer); } 

家长计划代码:

 /* cc parent.c -o parent */ int main (int argc, char **argv) { pid_t pid = fork(); if (pid < 0) { perror("fork"); exit(EXIT_FAILURE); } else if (pid == 0) { execvp(*(argv+1), argv+1); } else { // while(1); if while(1) or wait() is used, child process can wait for input exit(1); } } 

在zsh shell中:

 zsh>: ./parent ./child zsh>: This is what child program read: // read nothing and print nothing 

终端由前台进程组控制。 当shell调用父进程时,它使父进程前台进程组的领导者。 孩子继承那个组并且可以访问终端。

但是,当父节点退出时,shell会收回终端的控制权并成为前台进程组的负责人。 孩子不再处于前台进程组,因此无法访问终端。 在这种情况下, fgets()将返回NULL ,并将设置一个错误代码。

如果从终端以外的其他位置(如管道)接收输入,则会看到程序按预期工作。 例如:

 $ echo test | ./parent ./child 

所以这个问题只发生在输入来自终端的时候。

回想起来 ,如果检查了fgets的错误代码,回答这个问题会更直截了当。 在这种情况下,fgets返回null,但是你需要检查feof()和/或者ferror()来确定这是否意味着文件已经到达(stdin关闭)或者是否有错误。 在这种情况下,NULL意味着有一个EIO错误。

较早的错误答案(请参阅评论线程的解释,因为冗长的讨论留在这里):当你分叉时,子进程继承stdin等。当父进程退出时,它关闭stdin,所以孩子试图从关闭描述符,并没有得到任何。 通过添加对wait()的调用,可以使stdin保持打开状态,从而使您的子程序按预期工作。

打印缓冲区之前,应该检查fgets()的返回值。 检查fgets是否不返回NULL,然后只打印缓冲区。