在多线程进程中,exec必须立即遵循fork吗?

在多线程进程中,exec必须立即遵循fork吗?,c,multithreading,pthreads,exec,fork,C,Multithreading,Pthreads,Exec,Fork,情况: 我有一个用C编写的多线程程序。如果其中一个线程分叉,则使用exec()将子进程替换为另一个,父进程等待子进程退出 问题: 通过fork()创建子进程后,有几行代码编译要在以下exec()命令中使用的参数 假设 我假设在由fork()创建的子进程和由exec()替换的子进程之间,子进程(作为父进程的副本)将拥有父进程的所有线程,因此这些线程将运行(尽管运行时间很短),这对吗 如果是这样,在fork()之后立即调用exec()是正确的解决方案吗?只有调用fork的线程才会在新进程中运行。但是

情况: 我有一个用C编写的多线程程序。如果其中一个线程分叉,则使用exec()将子进程替换为另一个,父进程等待子进程退出

问题: 通过fork()创建子进程后,有几行代码编译要在以下exec()命令中使用的参数

假设 我假设在由fork()创建的子进程和由exec()替换的子进程之间,子进程(作为父进程的副本)将拥有父进程的所有线程,因此这些线程将运行(尽管运行时间很短),这对吗


如果是这样,在fork()之后立即调用exec()是正确的解决方案吗?

只有调用
fork
的线程才会在新进程中运行。但是,在
exec
之前可以调用的函数有一些限制。发件人:

应创建一个具有 单线程。如果是多线程 进程调用新进程
fork()
应包含呼叫的副本 线程及其整个地址空间, 可能包括美国 互斥体和其他资源。 因此,为了避免错误 子进程只能执行 异步信号安全操作,直到 例如
exec
函数之一的时间 被称为。叉 可以通过以下方式建立处理程序: 函数在 维持申请的命令 跨越
fork()
调用的不变量

我相信这意味着,只要有多线程,您一般都会没事的 库正确使用
pthread\u atfork

编辑:该页面进一步解释了库如何保护自身:

预期用途是准备 处理程序获取所有互斥锁和 其他两个fork处理程序将释放 他们

例如,应用程序可以提供 一种准备程序,用于获取 库中必要的互斥 维护和提供孩子和家长 释放互斥锁的例程, 从而确保孩子得到一份工作 系统状态的一致快照 库(并且不支持任何互斥体) 左侧搁浅)。或者,一些 图书馆也许能够提供 一个子例程,用于重新初始化 库中的互斥体以及所有 关联状态到某个已知值 (例如,当 图像最初被执行)


正如@Matthew在回答中所写的,父进程中的其他线程将不存在于子进程中(如果您使用的是PThreads)


请注意,如果不是这样,那么将exec()调用放在对fork的调用“紧跟”之后是没有帮助的,因为其他线程仍有可能在调用exec()之前运行。但是,您可以通过在调用fork()之前锁定互斥锁来控制这一点-调用exec()实际上会破坏互斥锁。

我也认为,所有线程也会在子进程中复制。但事实并非如此。由于其他线程不会在子进程中复制,因此如果在exec之前使用互斥体/锁,则需要确保编写fork处理程序以正确处理它们。 这里有一篇关于它的文章。

引用的这段话表明标准库(例如,stdio、
atexit
malloc
、线程创建和销毁等)可能在内部使用同步资源,这些资源在
fork
之后可能处于不一致的状态?如果是这样,使用
pthread\u atfork
如何解决问题?@R,是的,可能。这取决于图书馆。在某些情况下,它们可以在fork之前锁定所有互斥体,然后在fork之后立即释放它们。在其他情况下,可以像从头开始一样重新初始化它们。我已经添加了
pthread\u atfork
中的一段相关内容。我不确定关于互斥体“基本上被破坏”的说法是否正确。正如我前面所说,锁有进入不一致状态的风险。这就是
pthread\u atfork
存在的原因。