在按函数execvp()
分叉并执行子程序之后,父进程退出。但是,这会导致子进程中的函数fgets()
立即返回,而不等待stdin
的输入。
我想退出父进程会向子进程发送一些信号,使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
答案 0 :(得分:4)
终端由前台进程组控制。当shell调用父对象时,它使父对象成为前台进程组的领导者。孩子继承该组并可以访问终端。
但是,当父进程退出时,shell将取回终端的控制权并成为前台进程组的领导者。子进程不再位于前台进程组中,因此无法访问终端。在这种情况下,fgets()
将返回NULL
,并将设置错误代码。
如果您从终端以外的某个位置(例如管道)接收输入,那么您将看到该程序按预期工作。例如:
$ echo test | ./parent ./child
所以只有当输入来自终端时才会出现此问题。
回想起来,如果检查了fgets错误代码,回答这个问题会更加直截了当。在这种情况下,fgets返回null,但是您需要检查feof()
和/或ferror()
以确定这是否意味着文件的末尾已到达(stdin已关闭)或出现错误。在这种情况下,NULL表示存在EIO
错误。
早期错误回答(请参阅评论主题以获取解释,因为讨论冗长而留在此处):
fork时,子进程继承stdin等。当父进程退出时,它会关闭stdin,因此子进程尝试从已关闭的描述符中读取并且什么也得不到。通过添加对wait()
的调用,您可以保持stdin打开,这样您的子程序就可以按预期工作。
答案 1 :(得分:0)
您应该在打印缓冲区之前检查fgets()的返回值。检查fgets是否不返回NULL,然后仅打印缓冲区。