【问题标题】:How to retain child process's access to the terminal after the parent closes父进程关闭后如何保留子进程对终端的访问
【发布时间】:2026-02-14 19:05:02
【问题描述】:

我正在尝试编写一个创建子进程然后自行关闭的程序。然后我需要孩子保持与终端的连接。

子进程按预期工作(等待终端输入,然后将其打印出来),直到父进程关闭。当父进程终止时,子进程不再等待输入,并且“fgets 错误”消息将无限期地在终端中打印出来。

这很奇怪,因为似乎在父级终止后标准输入关闭但子级的标准输出仍然连接到终端。

int main(){
int pid1;
pid1=fork();
if (pid1==-1){
   perror("fork");
   exit(EXIT_FAILURE);
}
if (pid1==0){
   while(1){
   char *data;
   char *result;

   result=fgets(data,100,stdin);
   if (result!=NULL){
      printf("%s\n",data);
   }
   else{
       printf("fgets error\n");
       sleep(1);
       }
   }
}
else
{
//The sleep below is for debugging purposes
sleep(5);
exit(EXIT_SUCCESS);
}   
}

在父进程终止后,有没有办法保持子进程的标准输入/标准输出从终端定向到终端? 任何帮助/解释将不胜感激。

【问题讨论】:

  • 我认为您的情况与Two children of same parent are not communicating using pipe if parent does not call wait()? 中的情况相同。现代作业控制外壳使用的tcsetpgrp() 调用是问题的一部分。我不清楚是否有办法解决它 - AFAICT,当控制进程拒绝子进程访问终端时,该拒绝是不可撤销且无可争议的。我开始尝试,但很难找到正确的设置。
  • 您使用未初始化的指针调用fgets()。这会导致问题,但可能不是您所描述的。
  • @JonathanLeffler:如果孩子不拥有控制终端并试图将其用作非控制终端,那么它可能会与 shell 争夺输入。 OP 要求的设置在逻辑上没有意义。

标签: c linux unix


【解决方案1】:

正如@Jonathan-Leffler 的另一个回答所指出的那样,这是由于在父进程完成时,shell 获得了stdin 的所有权。问题是,虽然stdout 可以由任意多个进程共享(输出只是混合),但stdin 不能轻松共享。

一种可能的解决方法,无需修改您的程序(让它成为./test)可能是:

$ cat | ./test

现在,shell 将等待 cat 完成,但在您键入 EOF (^D) 或写入 stdout 失败之前,cat 不会完成。但是即使你的父进程完成了,子进程中的重复fd也会继续消耗catted数据。

【讨论】:

    最近更新 更多