分叉如何影响进程的内存布局?

分叉如何影响进程的内存布局?

下图显示了进程的内存布局:

:

当某人forks()和一个新的人task_struct被分配时,进程的地址会发生什么?换句话说:想象一下有一个过程,所以下图成立。现在假设我做了一个叉子。会发生什么?

答案1

fork 后,您将拥有同一程序的两个副本。内核可以复制所有地址空间或者写时复制。在后一种情况下,文本和数据部分可能始终由两个进程共享,并且如果子进程需要修改堆栈,则堆栈将被复制,依此类推。

答案2

当一个进程被分叉时,Linux 会进行非常少量的复制,并使用写时复制方法。这种写时复制意味着如果两个进程(父进程和子进程)都在进行读取,它们将从完全相同的内存块中读取。一旦其中一个写入该内存,该内存就会被复制并且不再共享。

现在程序不知道发生了这种情况。这是因为内核为每个进程维护一个页表。当进程说“我想访问内存 0xbeef”时,内核会将其重新映射到物理内存中的实际位置。这是必要的,因为程序会将这些地址存储在变量中,因此当程序被分叉时,它无法知道内存中的数据是否或移动到哪里(所有存储在变量中的地址必须继续有效)。
这也是交换能够发挥作用的原因。内核可以获取保存数据的物理内存并将其存储到磁盘,但程序仍将引用地址 0xbeef,并且内核将对其进行转换。

因此,内核最终复制的绝对最小值是执行此地址映射的页表和任务结构(涵盖打开的文件、进程状态、待处理信号等)。

答案3

由于每个进程都被分配了自己的地址空间(“虚拟内存"),地址可能会保持不变,但引用转换表中的不同内存地址(修改时)。从进程的角度来看,它使用和看到的地址没有任何变化。

答案4

整个地址空间被克隆。换句话说,该图描述了分叉后的两个进程。之后,这些流程就会彼此分歧,因为它们各自以不同的方式改变事物。

相关内容