Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从多线程应用程序生成进程_C_Linux_Unix_Process_Fork - Fatal编程技术网

C 从多线程应用程序生成进程

C 从多线程应用程序生成进程,c,linux,unix,process,fork,C,Linux,Unix,Process,Fork,我的情况是,我需要从一个非常大的多线程应用程序中生成一个helper进程,我无法完全控制它 现在我正在使用fork()/exec()。这在很多情况下都有效,但在某些情况下,孩子会在exec()发生之前奇怪地崩溃。我怀疑这是因为fork() 我真的,真的很想找到一种方法来以原子方式启动一个进程,而不必fork()ing父进程:关闭所有文件描述符,按照我想要的方式设置环境,设置CWD等等。这应该可以避免fork()ing我的多线程父应用程序,以及处理文件描述符继承的所有恐惧,等等。posix_spa

我的情况是,我需要从一个非常大的多线程应用程序中生成一个helper进程,我无法完全控制它

现在我正在使用
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,看来您是在我更新它的同时更新的,您的更改没有保存(修复)。谢谢,但我