没有写时复制时的问题
最初在Unit系统中,在使用fork()
系统调用创建子进程的时候,会复制父进程的整个地址空间并把复制的那一份分配给子进程。这种情况比较耗时。因为它需要:
- 为子进程的页表分配空间
- 为子进程的页分配页面
- 初始子进程的页表
- 把父进程的页复制到子进程相应的页中。
创建一个地址空间的这种方法涉及许多内存访问,消耗许多CPU周期,并且完全破环了高速缓存中的内容。在大多数情况下,这种做法常常时毫无意义的,因为许多子进程通过装入一个新的程序开始它们的执行,这样就完全丢弃了所继承的地址空间。
Linux的fork()使用写时复制
写时复制技术时一种可以推迟甚至避免拷贝数据的技术。内核不需要复制整个地址空间,而是让父子进程共享同一个地址空间,只用在需要写入的时候才会复制地址空间,从而使各个进程拥有自己的地址空间。
写时复制
内核只为新生成的子进程创建虚拟空间结构,它们复制于父进程的虚拟空间结构,但是不为这些段分配物理内存,它们共享父进程的空间,当父进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间。
vfork()
这个方案直接利用父进程的虚拟地址空间,vfork()
并不会把父进程的地址空间完全复制给子进程,因为子进程会立即调用exec
或exit
,也就不会访问该地址空间了。在子进程调用exec
之前,它在父进程空间中运行。vfork()
保证子进程先运行,在子进程调用exec
或exit
之后父进程才能调度运行。
v1.5.2