我编写了一个程序,在其中创建了一个主线程,并使用system()
从该线程启动另一个进程。同样,我也使用main函数中的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;
}
答案 0 :(得分:3)
我的建议是:不要做自己想做的事情。如果要创建独立运行的子进程,请研究fork
和exec
family函数。 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
。
答案 1 :(得分:0)
我想您错过了两点:
首先,system
是一个同步呼叫。这意味着您的程序(或至少调用system
的线程)等待,以使子进程完成。因此,如果您的command
长时间运行,则主线程和辅助线程都将被阻塞,直到完成为止。
第二,您正在main
末尾“加入”工作线程。这是正确的做法,因为除非您加入或分离线程,否则您将无法定义行为。但是,这并不是您真正想做的。最终结果不是子进程在您的主进程结束之后继续运行...您的主进程仍然存在!它在pthread_join
调用中被阻止,该调用正在试图包装仍在运行command
的工作线程。
通常,假设您希望产生一个与主进程完全无关的新进程,则线程不是实现该进程的方法。即使您要分离线程,它仍然属于您的进程,并且仍然需要在进程终止之前让它完成。您无法使用线程从进程中分离出来。
相反,您将需要诸如fork
和exec
之类的OS功能(或围绕此功能的友好C ++包装器,如Boost.Subprocess)。这是从程序内部真正产生新进程的唯一方法。
但是,您可以作弊!如果command
是Shell命令,并且您的Shell支持后台作业,则可以将&
放在命令末尾(这是Bash语法的示例)以进行system
调用:
例如:
const std::string command = "./myLongProgram &";
// ^
不过,这又是一种hack和适当的fork机制,驻留在 内,为最大的可移植性和可预测性,应该首选程序的逻辑。