将后台进程发送到前台 < 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都指向终端,因此任何一个调用都可以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
}