C 从多线程应用程序生成进程
我的情况是,我需要从一个非常大的多线程应用程序中生成一个helper进程,我无法完全控制它 现在我正在使用C 从多线程应用程序生成进程,c,linux,unix,process,fork,C,Linux,Unix,Process,Fork,我的情况是,我需要从一个非常大的多线程应用程序中生成一个helper进程,我无法完全控制它 现在我正在使用fork()/exec()。这在很多情况下都有效,但在某些情况下,孩子会在exec()发生之前奇怪地崩溃。我怀疑这是因为fork() 我真的,真的很想找到一种方法来以原子方式启动一个进程,而不必fork()ing父进程:关闭所有文件描述符,按照我想要的方式设置环境,设置CWD等等。这应该可以避免fork()ing我的多线程父应用程序,以及处理文件描述符继承的所有恐惧,等等。posix_spa
fork()
/exec()
。这在很多情况下都有效,但在某些情况下,孩子会在exec()
发生之前奇怪地崩溃。我怀疑这是因为fork()
我真的,真的很想找到一种方法来以原子方式启动一个进程,而不必fork()
ing父进程:关闭所有文件描述符,按照我想要的方式设置环境,设置CWD等等。这应该可以避免fork()
ing我的多线程父应用程序,以及处理文件描述符继承的所有恐惧,等等。posix_spawn()
应该是理想的选择。不幸的是,在Linux上,posix_spawn()
是使用fork()
和exec()
实现的
vWork()
被定义为暂停父进程,直到子进程调用exec()
。这看起来更像是我想要的,但我的理解是,vWork()
现在通常被认为是历史遗迹,相当于fork()
——仍然是这样吗
处理这件事最不坏的方法是什么
请注意:
- 我无法在任何线程启动之前生成进程(因为我无法在该点运行代码)
- 由于外部需求,我无法重新设计我的应用程序,使其不需要helper流程
- 我不能在生成助手进程之前挂起所有线程,因为它们不属于我
这是在Linux上实现的。涉及Java,但我所有的代码都是C语言。如果只使用异步信号安全操作,则认为分叉多线程应用程序是安全的。POSIX:
应使用单个线程创建进程。如果多线程进程调用fork(),则新进程应包含调用线程及其整个地址空间的副本,可能包括互斥体和其他资源的状态。因此,为了避免错误,在调用某个exec函数之前,子进程只能执行异步信号安全操作。Fork处理程序可以通过pthread_atfork()函数建立,以便在Fork()调用中保持应用程序不变量
posix_spawn()不是最好的主意:
临时修改多线程进程的环境也很复杂,因为当环境安全时,所有线程都必须同意进行更改。但是,此成本仅由使用附加功能的posix_spawn()和posix_spawn()调用承担。由于广泛的修改不是通常的情况,并且在时间关键型代码中特别不可能,因此将大部分环境控制置于posix_spawn()和posix_spawn()之外是合适的设计
(见附件)
我猜您在从父资源复制时遇到了问题。您可以使用pthread_atfork()处理程序清理它们(您使用pthread,对吗?)。另一种方法是使用低级函数来创建被调用的进程。它几乎可以完全控制子进程应该从其父进程继承什么
[更新]
也许解决这个问题最简单的方法就是改变你的分叉方案。例如,您甚至可以在程序初始化所有资源之前创建一个新进程(fork)。例如,在创建所有线程之前,在main()中调用fork()。在子进程设置中,设置一个信号处理程序(例如SIGUSR2信号)和睡眠。当父进程需要执行某个新进程时,它会向子进程发送SIGUSR2信号。当child捕捉到它时,它调用fork/exec。如果您将自己限制为“原始”系统调用(syscall(SYS\u fork)
,syscalll(SYS\u execve,…)
等),那么调用fork
应该是安全的。调用任何glibc例程,你都会遇到很多麻烦
调用vfork
完全不是您想要的:只有调用vfork
的线程被挂起,其他线程将继续运行(并且在与vforking子线程相同的地址空间中)。这很可能使你的生活复杂化
直接调用clone
是可能的,但非常棘手。我们有一个实现,它允许从多线程应用程序(不幸的是不是开源)安全地分支子进程。这段代码非常复杂,而且非常长。既然您已经在使用线程,为什么不启动一个新的线程来调用system()
,并运行您需要的任何东西呢?多线程程序中的fork()没有固有的问题,但对于占用大量内存且线程繁忙的应用程序来说,它可能有点效率低下。system()通过执行fork()/exec()工作!使用fork()和线程的最大问题是,当fork()发生时,所有其他线程都会消失——不管它们是否在关键部分。并且锁、信号量等的状态在子系统中变得未定义。因此,如果一个线程位于一个MalCube()中,然后这个孩子调用MalCube(),可怕的事情就会发生(我想这是发生在我身上)。事实上,我已经对事情进行了重组,所以我使用vWork()和孩子唯一调用的函数exec(),我想我的崩溃已经停止了,但我仍然想要一个答案…@DavidGiven:Chiming In way later here,但我不希望posix_spawn
或system
在fork
和exec
之间进行非异步信号安全调用;因此,在多线程应用程序中使用它们应该是安全的,除非它们在其手册页中明确表示不安全。@Shahbaz-heh,看来您是在我更新它的同时更新的,您的更改没有保存(修复)。谢谢,但我