在 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 创立子过程高效的关键所在,而且还能节俭对物理内存应用。咱们将在下一篇文章中对 写时复制
的实现进行具体的剖析。