没有 atfork 处理程序的 fork+exec

fork+exec without atfork handlers

我有一个库,它注册了一个 atfork 处理程序(通过 pthread_atfork()),它在调用 fork() 时不支持多线程。就我而言,我不需要派生的环境可用,因为我只想在 fork() 之后立即调用 exec()。所以,我想要 fork() 但没有任何 atfork 处理程序。那可能吗?我会错过任何重要的边缘案例吗?

关于背景信息,库是 OpenBlas,问题描述 here and here

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

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

...
  syscall(SYS_fork);

这样就绕过了库,直接调用fork的系统调用。如果您的平台没有将 fork 实现为单个系统调用,您可能 运行 会遇到麻烦。对于 Linux,这只是意味着您应该改用 clone

考虑到这一点,我不确定我是否会推荐这样做。由于您是图书馆,因此您不知道 为什么 有人注册了 atfork。假设它无关紧要是糟糕的编程习惯。

所以你为了做一些可能会或可能不会破坏东西的东西而失去了可移植性,所有这些都是为了什么?节省一些函数调用?就个人而言,我只使用 fork.

您可以使用 vfork()(NPTL 实现不调用分叉处理程序)。尽管 POSIX 已从标准中删除 vfork,但它可能在您的实施中可用。

Fork handlers established using pthread_atfork(3) are not called when a multithreaded program employing the NPTL threading library calls vfork(). Fork handlers are called in this case in a program using the LinuxThreads threading library. (See pthreads(7) for a description of Linux threading libraries.)

或者,posix_spawn()。这类似于 vfork。手册页说:

According to POSIX, it unspecified whether fork handlers established with pthread_atfork(3) are called when posix_spawn() is invoked. On glibc, fork handlers are called only if the child is created using fork(2).

或者,syscall,直接使用SYS_cloneSYS_clone 是用于在 Linux 上创建线程和进程的系统调用号。所以 syscall(SYS_clone, SIGCHLD, 0); 应该可以工作,前提是你会立即执行。

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

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