使用system()创建独立的子进程
Use system() to create independent child process
我编写了一个程序,在该程序中,我在main中创建了一个线程,并使用system()
从该线程启动另一个进程。此外,我还使用主函数中的system()
启动了相同的过程。从线程启动的进程似乎仍然活着,即使父进程死了。但是从主函数调用的一个函数将随父函数一起消亡。知道为什么会发生这种情况吗。
请在下面找到代码结构:
void *thread_func(void *arg)
{
system(command.c_str());
}
int main()
{
pthread_create(&thread_id, NULL, thread_func, NULL);
....
system(command.c_str());
while (true)
{
....
}
pthread_join(thread_id, NULL);
return 0;
}
我的建议是:不要做你所做的。如果你想创建一个独立运行的子进程,请研究fork
和exec
家族函数。这就是system
将在"引擎盖下"使用的内容。
线程并不像进程那样真正独立。当"主"进程结束时,所有线程也将结束。在您的特定情况下,线程似乎继续运行,而主进程似乎因为pthread_join
调用而结束,它只需等待线程退出。如果删除联接调用,线程(和您的"命令"(将终止。
有一些方法可以分离线程,这样它们就可以更独立地运行(例如,你不必加入分离的线程(,但主进程仍然无法结束,相反,你必须结束主线程,只要有分离的线程在运行,这将使进程保持运行。
使用fork
和exec
实际上很简单,但不是很复杂:
int pid = fork();
if (pid == 0)
{
// We are in the child process, execute the command
execl(command.c_str(), command.c_str(), nullptr);
// If execl returns, there was an error
std::cout << "Exec error: " << errno << ", " << strerror(errno) << 'n';
// Exit child process
exit(1);
}
else if (pid > 0)
{
// The parent process, do whatever is needed
// The parent process can even exit while the child process is running, since it's independent
}
else
{
// Error forking, still in parent process (there are no child process at this point)
std::cout << "Fork error: " << errno << ", " << strerror(errno) << 'n';
}
要使用的exec
的确切变体取决于command
。如果它是可执行程序的有效路径(绝对路径或相对路径(,则execl
运行良好。如果是PATH
中的"命令",则使用execlp
。
这里有两点我认为你错过了:
首先,system
是一个同步呼叫。这意味着,您的程序(或者至少是调用system
的线程(等待子进程完成。因此,如果command
是长时间运行的,那么主线程和工作线程都将被阻塞,直到它完成。
其次,您正在"加入"main
末尾的工作线程。这是正确的做法,因为除非你连接或分离线程,否则你会有未定义的行为。然而,这并不是你真正想要做的。最终的结果并不是在你的主进程结束后,子进程继续。。。你的主要过程仍然存在!它在pthread_join
调用上被阻止,该调用正试图包装仍在运行command
的工作线程。
一般来说,假设你想生成一个与主进程完全无关的新进程,线程不是实现这一点的方法。即使你要分离线程,它仍然属于你的进程,你仍然需要在进程终止之前让它完成。不能使用线程从进程分离。
相反,您需要fork
和exec
等操作系统功能(或围绕此功能的友好C++包装器,如Boost.Subprocess(。这是从程序中真正生成新进程的唯一方法。
但是,你可以作弊!如果command
是一个shell命令,并且您的shell支持后台作业,那么您可以将&
放在命令的末尾(这是Bash语法的一个示例(,以进行system
调用:
- 要求shell启动一个新进程
- 等待它做那件事
- 新进程现在将继续在后台运行
例如:
const std::string command = "./myLongProgram &";
// ^
然而,同样,这是一种黑客攻击,并且驻留在中的适当的fork机制应该是您的程序逻辑的首选,以获得最大的可移植性和可预测性。
- 终止 QProcess 不会终止子进程
- 什么时候最好在子进程中使用 CPU 或 I/O 密集型代码 [ C++ ]
- 我们能否在stm32f中使用硬件定时器控制两个独立的进程
- 子进程更新共享 mmap 内存,但父进程没有更改
- 使用 waitpid 时等待子进程终止
- 使用重定向标准处理子进程中的 kbhit
- 由 JOB 中的进程启动的子进程是否可以将 JOB 属性设置为脱离作业?
- 是否可以将子进程的 stdout 重定向到父进程中的另一个文件?
- kill() 总是返回 0(成功),即使在子进程已经结束之后?
- 父进程和子进程之间的 POSIX 信号量
- 检测到由于操作系统内存不足而导致子进程终止
- 使用system()创建独立的子进程
- 从stdin读取时子进程挂起(fork/dup2竞争条件)
- 在 Bash 脚本中处理来自子进程的信号
- Qt C++ - 如何成功将数据传递给子进程?
- C++ 窗口本地系统模拟在子进程中失败
- 将类型化数组写入子进程 stdin 无法正常工作
- 将 nodejs 脚本作为子进程执行(而不是从其他脚本执行)
- 使用信号检测子进程何时终止的最佳方法是什么?
- 等待等待失效的子进程