linux 写时复制机制原理

  在linux系统中,调用fork系统调用创建子进程时,并不会把父进程所有占用的内存复制一份,而是与父进程公用相同的内存页,而当子进程或者父进程对内存页进行修改时才会进行复制----这就是著名的 写时复制 机制

  虚拟内存与物理内存

  进程的内存可以分为:虚拟内存物理内存

  •   物理内存:就是电脑安装的内存条,如果电脑安装了2GB的内存条,那么系统就用于0-2GB的物理内存空间
  •   虚拟内存:虚拟内存是使用软件虚拟的,在32位操作系统中,每个进程都独占4GB的虚拟内存空间

  应用程序使用的虚拟内存,比如C语言取地址操作符号& 所得到的地址就是虚拟内存地址。而虚拟内存地址 需要映射到物理内存地址 才能使用,如果使用没有映射的 虚拟内地址 ,将会导致 缺页异常

 虚拟内存地址 映射到物理内存地址如图所示:

  

 

 

如上图所示,进程A 与进程B的相同虚拟内存地址 映射到不通的物理内存地址,这就是不通进程的相同虚拟内存地址互不影响的原因。

 

写时复制原理

 前面介绍了 虚拟内存物理内存的概念,接下来将会介绍 linux 写时复制的原理。

前面说过,虚拟内存需要与物理内存进行映射才能使用,如果不同进程的 虚拟内存地址映射到相同的物理内存地址,那么就实现了共享内存的机制,如下图所示:

 

 

 

由于进程A的虚拟内存M 与进程B的虚拟内存M' 映射到相同的 物理内存G,所以当修改进程A虚拟内存M的数据时,进程B 虚拟内存M'的数据也会跟着改变。

linux为了加速创建子进程过程与节省内存使用的原因,实现了 写时复制 的机制。

写时复制 的原理大概如下:

  •   创建子进程时,将父进程的虚拟内存与物理内存映射关系复制到子进程中,并将内存设置为只读()
  •   当子进程或者父进程对内存数据进行修改时,便会触发写时复制机制:将原来的内存页复制一份新的,并重新设置其内存映射关系,将父子进程的内存读写权限设置为可读写。

写时复制 过程如下图所示:

 

 

 

从上图可知,当创建子进程时,父子进程指向相同的 物理内存,而不是将父进程所占用的 物理内存 复制一份。这样做的好处有两个:

  • 加速创建子进程的速度。

  • 减少进程对物理内存的使用。

但这个时候只能对内存进行读操作,如果父进程或子进程对内存进行写操作,那么将会触发 缺页异常,而在 缺页异常 处理中会对物理内存进行复制,并且重新映射其内存映射关系。

复制并重新映射到新的物理内存后,父子进程的虚拟内存就映射到不同的物理内存上,这时父子进程都可以对内存进行写操作而互不影响,所以需要把父子进程的内存读写权限设置为可读写。

posted @ 2021-07-28 12:39  pebblecome  阅读(246)  评论(0编辑  收藏  举报