叉子+;不带atfork处理程序的exec

叉子+;不带atfork处理程序的exec,c,linux,fork,exec,posix,C,Linux,Fork,Exec,Posix,我有一个库,它注册一个atfork处理程序(通过pthread\u atfork()),当调用fork()时,它不支持多个线程。在我的例子中,我不需要fork环境是可用的,因为我只想在fork()之后调用exec()。因此,我需要fork()但不需要任何atfork处理程序。可能吗?我会错过任何重要的边缘案例吗 关于背景信息,该库是OpenBlas,问题如下所述。是。以下内容应该适用于Linux(我认为,所有基于glibc的平台): 定义GNU源 #包括 #包括 ... syscall(SYS_

我有一个库,它注册一个
atfork
处理程序(通过
pthread\u atfork()
),当调用
fork()
时,它不支持多个线程。在我的例子中,我不需要fork环境是可用的,因为我只想在
fork()之后调用
exec()
。因此,我需要
fork()
但不需要任何
atfork
处理程序。可能吗?我会错过任何重要的边缘案例吗


关于背景信息,该库是OpenBlas,问题如下所述。

是。以下内容应该适用于Linux(我认为,所有基于
glibc
的平台):

定义GNU源
#包括
#包括
...
syscall(SYS_fork);
这将绕过库并直接调用
fork
的系统调用。如果您的平台没有将
fork
作为单个系统调用实现,您可能会遇到麻烦。对于Linux,这仅仅意味着您应该使用
clone

考虑到这一点,我不确定我是否会推荐这样做。既然你是一个图书馆,你就不知道为什么有人在atfork注册了
。假设它不相关是糟糕的编程实践

所以你失去了可移植性,为了做一些可能会或可能不会破坏东西的事情,都是以什么的名义?保存一些函数调用?就个人而言,我只会使用您可以使用的
fork
(NPTL实现不调用fork处理程序)。尽管POSIX已经从标准中删除了
vWork
,但它很可能在您的实现中可用

使用pthread_atfork(3)建立的Fork处理程序在 采用NPTL线程库调用的多线程程序 vWork()。在这种情况下,在使用 LinuxThreads线程库。(有关详细信息,请参阅pthreads(7) Linux线程库的说明。)

或。这类似于
vWork
。手册页上说:

根据POSIX,未指定在调用POSIX_spawn()时是否调用使用pthread_atfork(3)建立的fork处理程序。在glibc上,只有使用fork(2)创建子级时,才会调用fork处理程序

或者,
syscall
并直接使用
SYS\u clone
SYS\u clone
是用于在Linux上创建线程和进程的系统调用号。So
syscall(SYS\u clone,SIGCHLD,0)应该可以工作

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


(注意:这些选项主要局限于glibc/Linux)。

如果OpenBlas注册的atfork处理程序通常在多线程程序中不能可靠工作,那么OpenBlas在这方面就有缺陷
pthread_atfork()
除了该用例之外,没有其他预期用例。如果这确实是OpenBlas的一个问题,并且您不准备自己修复它或等待维护人员修复它,那么您最好的选择可能是选择一个不同的BLAS库。请注意,如果您在实现中可以使用此方法,那么它是直接调用
fork()
的替代方法。它没有处理间接调用
fork()
的情况,例如通过
system()
popen()
。我想没有办法让代码更独立于平台,例如,对于MacOSX,我需要其他代码?另一个问题:如果我打算在
fork()
之后立即调用
exec()
,那么运行任何atfork处理程序可能有什么原因?@Albert但是您的C库的fork不知道您将立即执行;-)即使这样做了,它仍然不能跳过fork处理程序,因为需要按照文档运行它们。如果您正在寻找可移植性,
posix_spawn
可能是您的最佳选择。@usr:当然不知道。但是,例如,
vfork()
似乎可以做到这一点,就像
fork()
一样,但不调用atfork处理程序。我的问题是,当我想在之后调用
exec()
时,是否有任何情况需要在这种情况下调用atfork处理程序。
pthread\u atfork
最常见的用例是在fork之后将多线程程序中的资源(互斥体、条件变量等)保持在子进程中的一致状态。如果您立即执行,则无需担心任何此类不一致性-您已经用新的流程映像完全替换了它。
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>

...
  syscall(SYS_fork);