在退出父进程后,子进程无法读取

时间:2014-02-15 05:21:55

标签: c unix process

在按函数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

2 个答案:

答案 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,然后仅打印缓冲区。