我有一个库,它注册了atfork
处理程序(通过pthread_atfork()
),它在调用fork()
时不支持多线程。在我的情况下,我不需要使用分叉环境,因为我只需要在fork()
之后立即致电exec()
。所以,我想fork()
,但没有任何atfork
处理程序。那可能吗?我错过任何重要的边缘情况吗?fork + exec无atfork处理程序
对于背景信息,库是OpenBlas,问题描述为here和here。
我有一个库,它注册了atfork
处理程序(通过pthread_atfork()
),它在调用fork()
时不支持多线程。在我的情况下,我不需要使用分叉环境,因为我只需要在fork()
之后立即致电exec()
。所以,我想fork()
,但没有任何atfork
处理程序。那可能吗?我错过任何重要的边缘情况吗?fork + exec无atfork处理程序
对于背景信息,库是OpenBlas,问题描述为here和here。
您可以使用vfork()
(NPTL实现不调用fork处理程序)。尽管POSIX从标准中删除了vfork
,但它很可能在您的实施中可用。使用pthread_atfork建立
叉处理程序(3)当 采用NPTL线程库多线程程序调用vfork的 不叫()。在这种情况下,叉处理程序在使用LinuxThreads线程库的程序中调用。 (参见用于Linux线程库的 描述并行线程(7)。)
或者,posix_spawn()
。这与vfork
类似。手册页上说:
根据POSIX,它未指定在调用posix_spawn()时是否调用使用pthread_atfork(3)建立的fork处理函数。在glibc上,只有在使用fork(2)创建孩子时才会调用fork处理程序。
或者,syscall
并直接使用SYS_clone
。 SYS_clone
是用于在Linux上创建线程和进程的系统调用号。所以syscall(SYS_clone, SIGCHLD, 0);
应该工作,只要你立即执行。
syscall(SYS_fork);
(由Shachar回答)可能也会起作用。但请注意,SYS_fork
在某些平台上不可用(例如,aarch64,ia64)。 SYS_fork
在Linux中被认为是过时的,它只是为了向后兼容,而Linux内核使用SYS_clone来创建所有“类型”的进程。
(注意:这些选项大多限于glibc/Linux)。
是的。以下应工作在Linux(和,我想,所有glibc
基于平台):
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
...
syscall(SYS_fork);
这绕过图书馆,直接调用系统调用fork
。如果您的平台未将fork
作为单个系统调用实施,则可能会遇到麻烦。对于Linux,这仅仅意味着您应该使用clone
来代替。
考虑到这一点,我不确定我会这样做。既然你是图书馆,你不知道为什么有人注册了atfork
。假设不相关的是糟糕的编程习惯。
因此,你失去了可移植性,以做一些可能或不可能破坏的东西,所有的名称,什么?保存几个函数调用?就个人而言,我只是使用fork
。
请注意,如果在您的实现中可以使用此方法,则可以直接调用fork()。它没有解决间接调用'fork()'的情况,比如通过'system()'或'popen()'来调用。 –
我想没有办法让代码更独立于平台,例如对于MacOSX,我需要其他代码?另一个问题:如果我打算在'fork()'后面调用'exec()',那么可能会有什么原因可以运行任何atfork处理程序? – Albert
@Albert但是你的C库的fork不知道你要立即执行;-)即使这样做了,它仍然不能跳过fork处理程序,因为它需要在每个文档中运行它们。也许,如果你正在寻找便携性,'posix_spawn'是你最好的选择。 – usr
如果OpenBlas注册了一个atfork处理函数,通常*在多线程程序中不能可靠地工作,那么OpenBlas在这方面就有问题了。 'pthread_atfork()'没有其他用例。如果这确实是OpenBlas的一个问题,并且你不准备自己修复它或者等待维护人员修复它,那么你最好的选择可能是选择一个不同的BLAS库。 –