2017-10-18 113 views
1

我有一个库,它注册了atfork处理程序(通过pthread_atfork()),它在调用fork()时不支持多线程。在我的情况下,我不需要使用分叉环境,因为我只需要在fork()之后立即致电exec()。所以,我想fork(),但没有任何atfork处理程序。那可能吗?我错过任何重要的边缘情况吗?fork + exec无atfork处理程序

对于背景信息,库是OpenBlas,问题描述为herehere

+0

如果OpenBlas注册了一个atfork处理函数,通常*在多线程程序中不能可靠地工作,那么OpenBlas在这方面就有问题了。 'pthread_atfork()'没有其他用例。如果这确实是OpenBlas的一个问题,并且你不准备自己修复它或者等待维护人员修复它,那么你最好的选择可能是选择一个不同的BLAS库。 –

回答

1

您可以使用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_cloneSYS_clone是用于在Linux上创建线程和进程的系统调用号。所以syscall(SYS_clone, SIGCHLD, 0);应该工作,只要你立即执行。

syscall(SYS_fork);(由Shachar回答)可能也会起作用。但请注意,SYS_fork在某些平台上不可用(例如,aarch64,ia64)。 SYS_fork在Linux中被认为是过时的,它只是为了向后兼容,而Linux内核使用SYS_clone来创建所有“类型”的进程。

(注意:这些选项大多限于glibc/Linux)。

1

是的。以下应工作在Linux(和,我想,所有glibc基于平台):

#define _GNU_SOURCE 
#include <unistd.h> 
#include <sys/syscall.h> 

... 
    syscall(SYS_fork); 

这绕过图书馆,直接调用系统调用fork。如果您的平台未将fork作为单个系统调用实施,则可能会遇到麻烦。对于Linux,这仅仅意味着您应该使用clone来代替。

考虑到这一点,我不确定我会这样做。既然你是图书馆,你不知道为什么有人注册了atfork。假设不相关的是糟糕的编程习惯。

因此,你失去了可移植性,以做一些可能或不可能破坏的东西,所有的名称,什么?保存几个函数调用?就个人而言,我只是使用fork

+0

请注意,如果在您的实现中可以使用此方法,则可以直接调用fork()。它没有解决间接调用'fork()'的情况,比如通过'system()'或'popen()'来调用。 –

+0

我想没有办法让代码更独立于平台,例如对于MacOSX,我需要其他代码?另一个问题:如果我打算在'fork()'后面调用'exec()',那么可能会有什么原因可以运行任何atfork处理程序? – Albert

+0

@Albert但是你的C库的fork不知道你要立即执行;-)即使这样做了,它仍然不能跳过fork处理程序,因为它需要在每个文档中运行它们。也许,如果你正在寻找便携性,'posix_spawn'是你最好的选择。 – usr