在 Linux 零碎中,调用 fork
零碎调用创立子过程时,并不会把父过程所有占用的内存页复制一份,而是与父过程共用雷同的内存页,而当子过程或者父过程对内存页进行批改时才会进行复制 —— 这就是驰名的 写时复制
机制。
上面咱们将剖析 Linux 写时复制(Copy On Write)
机制的原理。
虚拟内存与物理内存
过程的内存可分为 虚拟内存
和 物理内存
。
物理内存
:就是电脑装置的内存条,如果电脑装置了 2GB 的内存条,那么零碎就用于 0 ~ 2GB 的物理内存空间。虚拟内存
:虚拟内存是应用软件虚构的,在 32 位操作系统中,每个过程都独占 4GB 的虚拟内存空间。
应用程序应用的是 虚拟内存
,比方 C 语言取地址操作符号 &
所失去的地址就是 虚拟内存地址
。而 虚拟内存地址
须要映射到 物理内存地址
能力应用,如果应用没有映射的 虚拟内存地址
,将会导致 缺页异样
。
虚拟内存地址
映射到 物理内存地址
如下图所示:
如上图所示,过程 A 与过程 B 的雷同 虚拟内存地址
映射到不同的 物理内存地址
,这就是不同过程的雷同虚拟内存地址互不影响的起因。
写时复制原理
后面介绍了 虚拟内存
与 物理内存
的概念,接下来将会介绍 Linux 写时复制
的原理。
后面说过,虚拟内存
须要与 物理内存
进行映射能力应用,如果不同过程的 虚拟内存地址
映射到雷同的 物理内存地址
,那么就实现了共享内存的机制。如下图所示:
因为过程 A 的 虚拟内存 M
与过程 B 的 虚拟内存 M'
映射到雷同的 物理内存 G
,所以当批改过程 A 虚拟内存 M
的数据时,过程 B 虚拟内存 M'
的数据也会跟着扭转。
Linux 为了减速创立子过程过程与节俭内存应用的起因,实现了 写时复制
的机制。
写时复制
的原理大略如下:
- 创立子过程时,将父过程的
虚拟内存
与物理内存
映射关系复制到子过程中,并将内存设置为只读(设置为只读是为了当对内存进行写操作时触发缺页异样
)。 - 当子过程或者父过程对内存数据进行批改时,便会触发
写时复制
机制:将原来的内存页复制一份新的,并从新设置其内存映射关系,将父子过程的内存读写权限设置为可读写。
写时复制
过程如下图所示:
当创立子过程时,父子过程指向雷同的 物理内存
,而不是将父过程所占用的 物理内存
复制一份。这样做的益处有两个:
- 减速创立子过程的速度。
- 缩小过程对物理内存的应用。
如上图所示,当父过程调用 fork
创立子过程时,父过程的 虚拟内存页 M
与子过程的 虚拟内存页 M
映射到雷同的 物理内存页 G
,并且把父过程与子过程的 虚拟内存页 M
都设置为只读(因为设置为只读后,对内存页进行写操作时,将会产生 缺页异样
,从而内核能够在缺页异样处理函数中进行物理内存页的复制)。
当子过程对 虚拟内存页 M
进行写操作,便会触发 缺页异样
(因为曾经将 虚拟内存页 M
设置为只读)。在缺页异样处理函数中,对 物理内存页 G
进行复制一份新的 物理内存页 G'
,并且将子过程的 虚拟内存页 M
映射到 物理内存页 G'
,同时将父子过程的 虚拟内存页 M
设置为可读写。
总结
本篇文章次要介绍了 Linux 写时复制
的原理, 写时复制
是 Linux 创立子过程高效的关键所在,而且还能节俭对物理内存应用。咱们将在下一篇文章中对 写时复制
的实现进行具体的剖析。
咱们的公众号