为什么execve函数映射私有区域?

amj*_*jad 1 c linux virtual-memory

我正在阅读一本教科书,其中将 eexecve函数描述为:

假设当前进程中运行的程序进行如下调用:

execve("a.out", NULL, NULL);

execve 函数在当前进程中加载​​并运行包含在可执行目标文件 a.out 中的程序,有效地用 a.out 程序替换当前程序。加载和运行a.out需要以下步骤

  1. 删除现有用户区域
  2. 映射私人区域。为新程序的代码、数据、bss 和堆栈区域创建新的区域结构。所有这些新区域都是私有的写时复制

在此处输入图片说明

  1. 映射共享区域
  2. 设置程序计数器

我对第 2 步有点困惑,所以假设fork()分叉一个子进程并让子进程运行execve一个新程序,那么为什么execve将子进程的新区域映射为私有的写时复制?父进程不会与子进程共享内存,因为父子进程映射到不同的对象,为什么子进程害怕其他进程可能会写一些东西来影响它?

Sha*_*ger 5

如果您查看图表,大多数“写时私有复制”页面都是“零需求”页面。这就是 Linux 处理分配请求的方式;它写时复制映射零页。因此,如果您只是阅读该页面,您会看到它充满了零,但此时它并没有占用实际内存。只要您需要写入它,它就会无缝地创建一个新的“真实”页面,其中填充零并将您的写入应用到它。

对于其余部分,如该.data部分,它映射到可执行文件的原始数据中,但您不想修改磁盘上的文件,因为您重新分配了一个全局变量,因此再次使用了写时复制。

基本上,它不是从原始程序“复制”真实页面,它只是一种从操作系统向程序提供一致归零页面的策略,并以允许在需要时进行修改的方式廉价提供对原始可执行文件数据的访问。