fork
,那么如果我立即在子进程中执行exec
,我是否相对安全?在exec
之前,哪些操作是安全的?如果执行
fork
的线程然后在调用exec
之前释放互斥锁,这会导致问题吗?如果我尝试在父进程在fork
之前拥有(可能仍然拥有)的子进程中获取互斥锁会发生什么?答案在不同平台上是否不同?我主要关心Unix变体,特别是Linux。但我也很好奇NT。当然,NT(据我所知)没有
fork
。fork
,那么如果我立即在子进程中执行exec
,我是否相对安全?在exec
之前,哪些操作是安全的?fork
的线程然后在调用exec
之前释放互斥锁,这会导致问题吗?如果我尝试在父进程在fork
之前拥有(可能仍然拥有)的子进程中获取互斥锁会发生什么?fork
。fork
相关的问题。它还提示了进程的子进程和父进程在 fork
发生前后应该是有效的。
更新:RATIONALE 部分是非规范的,并且与标准的其他部分存在冲突。请参见 Dave Butenhof 的 此缺陷报告 以获取更多详细信息。
fork
后立即执行 exec
对于任何多线程程序状态(即持有任何互斥量的线程)都应该是安全的。在 fork
和 exec
之间可能发生的事情如下:
最重要的是,在子进程中只复制了一个线程(调用 fork
的线程)。因此,任何在调用 fork
时由 另一个 线程持有的互斥量都会永久锁定。也就是说(假设未设置进程共享的互斥量),其在子进程中的 副本 会被永久锁定,因为没有线程来解锁它。
如果可能的话,在 fork
后释放互斥量是安全的,即,如果调用 fork
的线程在第一次拥有该互斥量。这通常是 pthread_atfork
处理程序的工作方式:在 fork
之前锁定互斥量,在子进程中解锁并在父进程中解锁。
关于获取进程在 fork
前所拥有的互斥量(记住,我们讨论的是子进程地址空间中的副本):如果是由 fork
调用线程 拥有 的,则适用于递归锁定(适用于 PTHREAD_MUTEX_RECURSIVE
);如果由另一个线程拥有,则它将永久锁定,并且无法重新获取。
通过注册适当的 pthread_atfork
处理程序,第三方库可以提供在 fork
和 exec
之间安全使用的保证。(我希望这主要来自编程语言运行时,而不是通用库)。
在fork()之后执行exec()是安全的,前提是互斥锁由将被exec()替换的程序所拥有。如果互斥锁是库的一部分,并且正在保护必须串行访问的资源,则应调用pthread_atfork()来注册回调:
POSIX标准限制了在fork()和exec()之间允许的系统调用类型,只允许所谓的异步信号安全系统调用。创建线程没有明确列为异步信号安全系统调用,因此POSIX不允许子进程在fork()和exec()之间创建线程。具有讽刺意味的是,解锁互斥锁也没有明确列为异步信号安全系统调用,因此如果fork()的目的是执行exec(),则在子进程中严格来说也不允许解锁互斥锁 - 这可能是标准中的一个疏漏。