下图显示了进程的内存布局:
:
当某人forks()
和一个新的人task_struct
被分配时,进程的地址会发生什么?换句话说:想象一下有一个过程,所以下图成立。现在假设我做了一个叉子。会发生什么?
答案1
答案2
当一个进程被分叉时,Linux 会进行非常少量的复制,并使用写时复制方法。这种写时复制意味着如果两个进程(父进程和子进程)都在进行读取,它们将从完全相同的内存块中读取。一旦其中一个写入该内存,该内存就会被复制并且不再共享。
现在程序不知道发生了这种情况。这是因为内核为每个进程维护一个页表。当进程说“我想访问内存 0xbeef”时,内核会将其重新映射到物理内存中的实际位置。这是必要的,因为程序会将这些地址存储在变量中,因此当程序被分叉时,它无法知道内存中的数据是否或移动到哪里(所有存储在变量中的地址必须继续有效)。
这也是交换能够发挥作用的原因。内核可以获取保存数据的物理内存并将其存储到磁盘,但程序仍将引用地址 0xbeef,并且内核将对其进行转换。
因此,内核最终复制的绝对最小值是执行此地址映射的页表和任务结构(涵盖打开的文件、进程状态、待处理信号等)。
答案3
答案4
整个地址空间被克隆。换句话说,该图描述了分叉后的两个进程。之后,这些流程就会彼此分歧,因为它们各自以不同的方式改变事物。