C++ 使用system()创建独立的子进程

C++ 使用system()创建独立的子进程,c++,multithreading,pthreads,fork,system-calls,C++,Multithreading,Pthreads,Fork,System Calls,我编写了一个程序,在主线程中创建一个线程,并使用system()从该线程启动另一个进程。此外,我还使用main函数中的system()启动相同的过程。从线程启动的进程似乎保持活动状态,即使父进程死亡。但是从主函数调用的一个将随父函数一起消亡。你知道为什么会这样吗 请在下面查找代码结构: void *thread_func(void *arg) { system(command.c_str()); } int main() { pthread_create(&a

我编写了一个程序,在主线程中创建一个线程,并使用
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;
}

我的建议是:不要做你所做的。如果要创建独立运行的子进程,请研究和函数。这就是
系统
将使用的“发动机罩下”

线程并不像进程那样真正独立。当“主”进程结束时,所有线程也结束。在您的特定情况下,线程似乎继续运行,而主进程似乎由于
pthread\u 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';
}
intpid=fork();
如果(pid==0)
{
//我们在子进程中,执行命令
execl(command.c_str()、command.c_str()、nullptr);
//如果execl返回,则表示出现错误

std::cout这里有两点我认为您遗漏了:

首先,
system
是一个同步调用。这意味着,您的程序(或者至少是调用
system
的线程)等待子线程完成。因此,如果
命令
长期运行,主线程和工作线程都将被阻塞,直到它完成

第二,你正在“加入”位于
main
末尾的工作线程。这是正确的做法,因为除非您加入或分离线程,否则您的行为未定义。但是,这不是您真正想要做的。最终结果不是子进程在主进程结束后继续…您的主进程仍然处于活动状态!它在主进程上被阻止
pthread\u join
调用,该调用正在尝试包装仍在运行的工作线程
命令

一般来说,假设您希望生成一个与主进程完全无关的新进程,线程不是这样做的方式。即使您要分离线程,它仍然属于您的进程,并且您仍然需要让它在进程终止之前完成。您不能使用线程从进程分离

而不是需要OS特性,如<代码> Fooe<代码>和<代码> Exc< /Cube >(或围绕这个功能的友好C++包装,如Boosix.SuPalPosits)。这是唯一真正地从程序中产生新进程的方法。

但是,您可以作弊!如果
命令
是一个shell命令,并且您的shell支持后台作业,那么您可以将
&
放在命令末尾(这是Bash语法的一个示例),以进行
系统
调用:

  • 请壳牌公司衍生出一个新流程
  • 等它这么做吧
  • 新进程现在将继续在后台运行
例如:

const std::string command = "./myLongProgram &";
//                                           ^

然而,同样,这是一种黑客攻击,为了获得最大的可移植性和可预测性,应该优先选择驻留在程序逻辑中的适当的fork机制。

我同意答案。此外,如果您只需要捕获命令的输出,而不需要在主进程死亡后运行它,那么这很有用:@ErikAlapäGood链接。但公认的答案确实存在
while(!feof(…)
循环的缺陷(如注释中所指出的)。我不需要双叉,因为我希望父进程继续,而不是等待子进程。@yashkapor除非您想获得子进程的退出状态,否则您永远不需要等待它。如果子进程成为孤立进程,则“init”进程将作为父进程接管,并在子进程结束时收获它。@某个程序员我尝试了您发布的上述代码示例。因此,每当我使用Ctrl+C终止父进程时,子进程也会放弃您对
thread\u func()的定义
不正确-它缺少参数。请看哪个示例。@kiner_shah这只是一个骨架。我的实际代码中确实有这个东西