将后台进程发送到前台
send background process to foreground
我的一个c++程序调用fork(),子程序立即执行另一个程序。我必须放置与子项的交互,但同时终止其父项,因为它的可执行文件将被替换。我需要以某种方式将孤儿放回前台,这样我就可以通过bash与它进行交互——我目前只得到它的输出。因此,我要么需要将父级发送到后台,将子级发送到前台,然后终止父级,要么在父级终止时立即将子级发到后台。
据我所知,在父进程终止之前,我必须将子进程设置为进程组组长。通过大量借用这个线程,我到达了以下测试场(注意,这不是完整的程序-它只是概述了过程):
int main(int argc, char *argcv[])
printf("%in", argc);
printf("nhello, I am %in", getpid());
printf("parent is %in", getppid());
printf("process leader is %in", getsid(getpid()));
int pgrp;
std::stringstream pidstream;
pidstream << tcgetpgrp(STDIN_FILENO);
pidstream >> pgrp;
printf("foreground process group ID %in", pgrp);
if(argc==1)
{
int child = fork();
if(!child) {execl("./nameofthisprogram","nameofthisprogram", "foo", NULL);}
else
{
signal(SIGTTOU, SIG_IGN);
usleep(1000*1000*1);
tcsetpgrp(0, child);
tcsetpgrp(1, child);
std::stringstream pidstream2;
pidstream2 << tcgetpgrp(STDIN_FILENO);
pidstream2 >> pgrp;
printf("foreground process group ID %in", pgrp);
usleep(1000*1000*3);
return 0;
}
}
// signal(SIGTTOU, SIG_IGN); unnecessary
int input;
int input2;
printf("write somethingn");
std::cin >> input;
printf("%in", input);
usleep(1000*1000*3);
printf("%in", input);
printf("write something elsen");
std::cin >> input2;
usleep(1000*1000*3);
printf("%in", input2);
return 0;
使用上面的代码,在我得到第一个输入的提示后,父级就死了。如果我将答案延迟到父母去世之后,它会拾取第一个输入字符并再次打印。对于input2,程序不等待我的输入。因此,似乎在第一个字符之后,输入就完全终止了。我处理这个问题是根本错误的,还是仅仅是重新分配几个id并改变一些信号的问题?
我发现这里有一些错误。
- 您永远不会将子进程放在自己的进程组中;因此,它保留在原始的中,因此与父级一起处于前台
- 您正在呼叫
tcsetpgrp()
两次;它只需要调用一次。假设没有重定向,stdin和stdout都引用终端,因此任何一个调用都可以
使用上面的代码,在我得到第一个输入的提示后,父级就死了。如果我将答案延迟到父母去世之后,它会拾取第一个输入字符并再次打印。对于input2,程序不等待我的输入。因此,似乎在第一个字符之后,输入就完全终止了。
您在这里观察到的是1.
的直接结果:由于两个进程都在前台,所以它们都在争相从stdin读取,结果是未定义的。
我需要以某种方式将孤儿放回前台,这样我就可以通过bash与它进行交互——我目前只得到它的输出。
据我所知,您可能希望在fork()/exec()
之后与execute的子级进行交互。要做到这一点,子进程需要在自己的进程组中,并且需要放在前台。
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()
对。我们这样做是因为我们不知道哪个将首先被调度,并且我们希望避免竞争条件,在这种情况下,exec’ed程序将在父级有时间将其放在前台之前尝试从stdin读取(因此接收到一个SIGTTIN,该SIGTTIN将停止进程)。我们也忽略SIGTTOU,因为我们知道子级或父级将接收到一个带有对tcsetpgrp()
的调用的SIGTTOU。
- boost::进程间消息队列引发错误
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 如何制作启动 Python 脚本的 linux 后台进程(在 c 中)
- 如何使用 std::in 和 getline() 检测后台进程中从 bash 注入的输入
- C++程序将进程置于前台(如果已在运行),否则创建一个新进程
- 使用 POCO 启动后台进程
- 如何仅在C中向后台进程发送SIGINT
- 程序在前台工作,但不在后台使用nohup
- 识别后台进程并在 C++ WIN32 中置于前台
- 在 C 语言的后台运行进程
- 如何在后台进程上处理来自Windows任务管理器的"End Task"?
- 在Linux中,如何在父进程死后将子进程留在前台
- 将后台进程发送到前台
- 在arduino上运行后台进程
- Pidof从一个后台脚本到另一个后台进程
- 运行后台进程Linux简单shell.c++
- 在后台运行的进程Get失败
- 将execv在前台或后台运行
- 如何将在后台运行的子进程移到前台
- 使用system()执行后台进程