我在glibc中使用vfork()
,根据vfork()
的手册页:
使用pthread_atfork(3)建立的Fork处理程序不被调用当一个多线程程序使用NPTL线程库时调用vfork()。类中调用Fork处理程序程序使用LinuxThreads线程库。
在NPTL上分叉处理程序没有被调用。在我的特殊情况下,我需要使用此保护因此,调用fork处理程序的方式将与调用fork()
时相同。
是否有一种方法可以使pthread库调用已注册的处理程序,甚至手动调用它们?
我想到使用clone()
,因为它提供了更精确的克隆进程控制,但它也避免了分叉处理程序:
使用pthread_atfork(3)注册的处理程序不执行在克隆呼叫中。
还可以阅读如何重置pthread_atfork注册的处理程序-在我的情况下,我不想删除处理程序,而只想调用它们。
谢谢。
如果您成功地做到了这一点,您的程序将变成损坏。有一个原因是否有办法使pthread库调用已注册的处理程序,甚至手动调用它们?
pthread_atfork
处理程序没有在vfork
上调用。
pthread_atfork
处理程序的典型用法是保证父进程中持有的任何锁在fork
之后在子进程和父进程中都处于一致状态。
如果没有处理程序,假设线程T1
持有锁L
,线程T2
调用fork
。因为只有T2
会被复制到子进程中,所以L
将永远处于锁定状态。如果T2
需要这个锁(假设它是malloc
锁),T2
将死锁(T1
不存在于子进程中)。
解决方案:pthread_atfork
处理程序。在父进程中prepare()
将获取L
,parent()
和child()
处理程序将分别在父进程和子进程中解锁L
的自己的实例。一切都很幸福1。
现在考虑如果在vfork
之后做同样的事情会发生什么。prepare()
按预期获取L
,但是当您调用parent()
和child()
时,它们会解锁L
的同一个实例(因为父进程和子进程共享内存)。因此,L
被解锁两次,破坏了它!
1在实践中,在多线程程序中调用fork
或vfork
是充满危险的,并且在任意库存在的情况下安全地执行此操作几乎是不可能的。