个人博客

爱写代码的小书童

马上订阅 个人博客 RSS 更新: https://zofun.github.io/atom.xml

fork()与写时复制

2020年5月15日 16:51

没有写时复制时的问题

最初在Unit系统中,在使用fork()系统调用创建子进程的时候,会复制父进程的整个地址空间并把复制的那一份分配给子进程。这种情况比较耗时。因为它需要:

  • 为子进程的页表分配空间
  • 为子进程的页分配页面
  • 初始子进程的页表
  • 把父进程的页复制到子进程相应的页中。

创建一个地址空间的这种方法涉及许多内存访问,消耗许多CPU周期,并且完全破环了高速缓存中的内容。在大多数情况下,这种做法常常时毫无意义的,因为许多子进程通过装入一个新的程序开始它们的执行,这样就完全丢弃了所继承的地址空间。

Linux的fork()使用写时复制

写时复制技术时一种可以推迟甚至避免拷贝数据的技术。内核不需要复制整个地址空间,而是让父子进程共享同一个地址空间,只用在需要写入的时候才会复制地址空间,从而使各个进程拥有自己的地址空间。

写时复制

内核只为新生成的子进程创建虚拟空间结构,它们复制于父进程的虚拟空间结构,但是不为这些段分配物理内存,它们共享父进程的空间,当父进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间。

YsJAk4.png

vfork()

这个方案直接利用父进程的虚拟地址空间,vfork()并不会把父进程的地址空间完全复制给子进程,因为子进程会立即调用execexit,也就不会访问该地址空间了。在子进程调用exec之前,它在父进程空间中运行。vfork()保证子进程先运行,在子进程调用execexit之后父进程才能调度运行

YstpZT.png