调用 fork 时是否复制线程?

Are threads copied when calling fork?

如果我有一个程序 运行 线程并在基于 unix 的系统上调用 fork(),线程是否被复制?我知道当前进程的虚拟内存被复制 1:1 到新产生的进程。我知道线程在进程的虚拟内存中有自己的堆栈。因此,至少也应该复制线程堆栈。但是,我不知道是否有更多的线程不驻留在虚拟内存中,因此不会被复制。如果没有,这两个进程是共享线程还是独立副本?

man fork:

The child process is created with a single thread—the one that called fork(). The entire virtual address space of the parent is replicated in the child, including the states of mutexes, condition variables, and other pthreads objects; the use of pthread_atfork(3) may be helpful for dealing with problems that this can cause.

没有

线程未在 fork() 上复制。 POSIX 规范说(强调是我的):

fork - create a new process

A process shall be created with a single thread. If a multi-threaded process calls fork(), the new process shall contain a replica of the calling thread and its entire address space, possibly including the states of mutexes and other resources. Consequently, to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called.

为了避免这个问题,pthread_atfork() 函数可以提供帮助。

来自 The Open Group Base Specifications Issue 7, 2018 edition's fork:

A process shall be created with a single thread. If a multi-threaded process calls fork(), the new process shall contain a replica of the calling thread and its entire address space, possibly including the states of mutexes and other resources. Consequently, to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called.

When the application calls fork() from a signal handler and any of the fork handlers registered by pthread_atfork() calls a function that is not async-signal-safe, the behavior is undefined.

最初,"fork" 是通过将任务写入磁盘然后修改任务 ID 而不是在不同的线程中读取(如果将任务与不同的任务交换就会完成)来实现的图像仍在内存中并继续执行(作为新任务)。这是对基本任务切换机制的一个非常简单的修改,其中一次只有一个任务会占用 RAM 内存。

当然,随着内存管理变得更加精细,此方案已被修改以适应新环境。