为什么较新的 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 免受竞争条件的影响?
对于大型进程,vfork
比 fork
更有效,因为地址 space 根本不需要重复。最初,有人担心在存在文件操作的情况下正确的取消处理需要使用 fork
,但最终确定当前基于 vfork
的实现是足够的。
vfork
在 qemu-user 和 Microsoft 的仿真中仍然存在问题,但是使用 posix_spawn
时通常看不到错误,因为它实际上并不使用 vfork
,而是 vfork
-style clone
带有单独堆栈的系统调用,这样即使父进程没有正确暂停,子进程中的堆栈也不会被破坏。
一些具有背景信息的资源:
我正在跟踪 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 免受竞争条件的影响?
vfork
比 fork
更有效,因为地址 space 根本不需要重复。最初,有人担心在存在文件操作的情况下正确的取消处理需要使用 fork
,但最终确定当前基于 vfork
的实现是足够的。
vfork
在 qemu-user 和 Microsoft 的仿真中仍然存在问题,但是使用 posix_spawn
时通常看不到错误,因为它实际上并不使用 vfork
,而是 vfork
-style clone
带有单独堆栈的系统调用,这样即使父进程没有正确暂停,子进程中的堆栈也不会被破坏。
一些具有背景信息的资源: