Linux 中 fork() 会立即复制整个进程堆吗?

Linux 中 fork() 会立即复制整个进程堆吗?

Afork()系统调用从正在运行的进程克隆子进程。除了 PID 之外,这两个进程完全相同。

当然,如果进程只是从堆中读取而不是写入,则复制堆将浪费大量内存。

整个进程堆都被复制了吗?是否以只有写入才会触发堆复制的方式进行了优化?

答案1

Linux 内核在fork()调用时确实实现了 Copy-on-Write。执行系统调用时,父级和子级共享的页面将被标记为只读。

如果在只读页上执行写入操作,则会复制该页,因为两个进程之间的内存不再相同。因此,如果仅执行读取操作,则根本不会复制页面。

答案2

整体offork()是使用mmap/copy on write实现的。

这不仅影响堆,还影响共享库、堆栈、BSS 区域。

顺便说一句,这意味着 fork 是一个极其轻量级的操作,直到生成的 2 个进程(父进程和子进程)实际开始写入内存范围。此功能是分叉炸弹致命性的一个主要因素 - 在内核因页面复制和区分而过载之前,您最终会遇到太多进程。

您将很难在现代操作系统中找到内核执行硬拷贝的操作示例(设备驱动程序是例外) - 使用虚拟机功能要容易得多且效率更高。

Evenexecve()本质上是“请 mmap 二进制文件/ld.so/诸如此类的东西,然后执行”——VM 负责将进程实际加载到 RAM 并执行。本地未初始化的变量最终从“零页”进行映射 - 包含零的特殊只读写时复制页,本地初始化变量最终从二进制文件本身进行映射(再次是写时复制), ETC。

答案3

Linux 提供写时复制。fork创建新进程时,分配的页面被标记为只读并在父进程和子进程之间共享。当其中任何一个尝试修改页面时,就会生成页面错误,从而导致复制页面并适当调整页表。

相关内容