为什么较新的 glibc 使用 vfork 而不是 fork 来实现 posix_spawn?

Why does newer glibc implement posix_spawn with vfork instead of fork?

我正在跟踪 posix_spawn glibc 2.17 和 glibc 2.27 中的源代码。

(glibc 2.17: sysdeps/posix/spawni.c)

(glibc 2.27: sysdeps/unix/sysv/linux/spawni.c)

我发现 glibc 2.17 根据标志和文件操作使用 vfork 或 fork。

我猜这是由于多线程安全或竞争条件。

但在 glibc 2.27 中,它只使用 vfork 创建子进程。

为什么 glibc 改变了实现?

较新的 linux 内核是否能更好地保护 vfork 免受竞争条件的影响?

对于大型进程,

vforkfork 更有效,因为地址 space 根本不需要重复。最初,有人担心在存在文件操作的情况下正确的取消处理需要使用 fork,但最终确定当前基于 vfork 的实现是足够的。

vfork 在 qemu-user 和 Microsoft 的仿真中仍然存在问题,但是使用 posix_spawn 时通常看不到错误,因为它实际上并不使用 vfork,而是 vfork-style clone 带有单独堆栈的系统调用,这样即使父进程没有正确暂停,子进程中的堆栈也不会被破坏。

一些具有背景信息的资源: