将后台进程发送到前台 < P>一个C++程序,调用Frk(),而孩子立即执行另一个程序。我必须让它与子对象交互,但同时终止它的父对象,因为它的可执行文件将被替换。我需要让孤儿回到前台,这样我就可以通过bash与它进行交互——我目前只得到它的输出。因此,我要么需要将父对象发送到后台,将子对象发送到前台,然后终止父对象,要么在父对象终止时立即将子对象发送到后台

将后台进程发送到前台 < P>一个C++程序,调用Frk(),而孩子立即执行另一个程序。我必须让它与子对象交互,但同时终止它的父对象,因为它的可执行文件将被替换。我需要让孤儿回到前台,这样我就可以通过bash与它进行交互——我目前只得到它的输出。因此,我要么需要将父对象发送到后台,将子对象发送到前台,然后终止父对象,要么在父对象终止时立即将子对象发送到后台,c++,c,linux,bash,C++,C,Linux,Bash,据我所知,在父进程终止之前,我必须将子进程设置为进程组组长。 借助于我的慷慨贷款,我来到了以下试验场(注意,这不是完整的计划-它只是概述了程序): intmain(intargc,char*argcv[]) printf(“%i\n”,argc); printf(“\nhello,我是%I\n”,getpid()); printf(“父项是%i\n”,getppid()); printf(“进程负责人是%i\n”,getsid(getpid()); int-pgrp; std::stringst

据我所知,在父进程终止之前,我必须将子进程设置为进程组组长。 借助于我的慷慨贷款,我来到了以下试验场(注意,这不是完整的计划-它只是概述了程序):

intmain(intargc,char*argcv[])
printf(“%i\n”,argc);
printf(“\nhello,我是%I\n”,getpid());
printf(“父项是%i\n”,getppid());
printf(“进程负责人是%i\n”,getsid(getpid());
int-pgrp;
std::stringstream-pidstream;
pidstream>pgrp;
printf(“前台进程组ID%i\n”,pgrp);
如果(argc==1)
{
int child=fork();
如果(!child){execl(“./nameofthisprogram”,“nameofthisprogram”,“foo”,NULL);}
其他的
{
信号(信号灯、信号灯);
usleep(1000*1000*1);
tcsetpgrp(0,儿童);
tcsetpgrp(1例,儿童);
std::stringstream pidstream2;
pid2>pgrp;
printf(“前台进程组ID%i\n”,pgrp);
usleep(1000*1000*3);
返回0;
}
}
//信号(信号灯、信号灯);不需要的
int输入;
int输入2;
printf(“写东西”\n);
std::cin>>输入;
printf(“%i\n”,输入);
usleep(1000*1000*3);
printf(“%i\n”,输入);
printf(“写其他东西”\n);
标准:cin>>输入2;
usleep(1000*1000*3);
printf(“%i\n”,input2);
返回0;
在上面的代码中,当我得到提示输入第一个输入时,父对象将死亡。如果我将答案延迟到父母去世之后,它将拾取第一个输入字符并再次打印。对于input2,程序不会等待我的输入。 因此,在第一个字符之后,输入似乎完全终止。
我的做法是根本错误的,还是仅仅是重新分配几个ID和改变一些信号的问题?

我在这里看到了一些错误

  • 您从未将子进程放入其自己的进程组中;因此,它将保留在原始图像中,因此与父对象一起位于前景中
  • 您正在调用
    tcsetpgrp()
    两次;它只需要调用一次。假设没有重定向,stdin和stdout都指向终端,因此任何一个调用都可以
  • 在上面的代码中,当我得到提示输入第一个输入时,父对象将死亡。如果我将答案延迟到父母去世之后,它将拾取第一个输入字符并再次打印。对于input2,程序不会等待我的输入。因此,在第一个字符之后,输入似乎完全终止

    您在这里看到的是
    1的直接结果。
    :由于这两个进程都在前台,它们都在竞相从stdin读取,并且结果未定义

    我需要让孤儿回到前台,这样我就可以通过bash与它进行交互——我目前只得到它的输出

    据我所知,您希望在
    fork()/exec()
    之后与被执行的孩子进行交互。要实现这一点,子进程需要位于自己的进程组中,并且需要放在前台

    int child = fork();
    signal(SIGTTOU, SIG_IGN);
    if (!child) {
      setpgid(0, 0); // Put in its own process group
      tcsetpgrp(0, getpgrp()); // Avoid race condition where exec'd program would still be in the background and would try to read from the terminal
      execl("./nameofthisprogram","nameofthisprogram", "foo", NULL);
    } else {
      setpgid(child, child); // Either setpgid call will succeed, depending on how the processes are scheduled.
      tcsetpgrp(0, child); // Move child to foreground
    }
    

    请注意,我们在父级和子级中都调用了
    setpgid()/tcsetpgrp()
    对。我们这样做是因为我们不知道哪个将首先被调度,并且我们希望避免这样的竞争条件,即在父程序有时间将其置于前台之前,被执行的程序将尝试从stdin读取数据(并因此接收到一个SIGTTIN,这将停止进程)。我们还忽略了sigttoo,因为我们知道子对象或父对象将通过调用
    tcsetpgrp()
    接收sigttoo

    前景?出身背景你是什么意思?你为什么需要
    叉子
    ?看起来你只有一个进程在做任何事情;您可以直接执行它,而无需分叉@ruakh这个程序只是实际程序中一个子进程的一个概要——子进程最终会删除父进程的可执行文件。
    
    int child = fork();
    signal(SIGTTOU, SIG_IGN);
    if (!child) {
      setpgid(0, 0); // Put in its own process group
      tcsetpgrp(0, getpgrp()); // Avoid race condition where exec'd program would still be in the background and would try to read from the terminal
      execl("./nameofthisprogram","nameofthisprogram", "foo", NULL);
    } else {
      setpgid(child, child); // Either setpgid call will succeed, depending on how the processes are scheduled.
      tcsetpgrp(0, child); // Move child to foreground
    }