Linux下写时拷贝技术(copy-on-write)

(一)cow概述

  在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后会调用exec系统调用,出于效率考虑,linux引用的写时拷贝技术,也就是只有进程空间的各段内容要发生变化时才会将父进程的内容复制一份给子进程
(关于fork()函数在https://blog.csdn.net/weixin_42647166/article/details/104478073文章中有详细探讨)
  在子进程的物理空间没有代码如何去执行exec系统调用呢?在fork()之后exec之前父子进程使用的是相同物理空间(内存区),子进程的代码段、数据段和堆栈段都指向父进程的物理空间,虽然两个虚拟空间不同,但对应的物理空间是一个。当父子进程中有更改相应段的行为发生时再为子进程相应的段分配物理空间,如果没有exec内核会给自进程的数据段、堆栈段分配相应的物理空间,而代码段继续共享父进程的物理空间,如果有exec导致两者执行代码不同,子进程的代码段会分配单独的物理空间

(二)cow详述

  现在有一个父进程P1,在虚拟地址空间上其分配了代码段、数据段和堆栈段,相应的内核要为这四个部分分配实际的物理块,即代码段块、数据段块、堆块和栈块。

1、fork()

  P1用fork()函数为进程创建了一个子进程P2,则内核:

  1. 复制P1的代码段,数据段,堆,栈这四个部分,注意是其内容相同。(虚拟空间)
  2. 为这四个部分分配物理块,其中除了代码段没有分配实际的物理空间而是指向的P1的代码段的物理空间,其余的数据段和堆栈段都分配有实际的物理空间,如下图所示:
    在这里插入图片描述

2、写时拷贝

  而写时拷贝:内核只为新生成的子进程创建虚拟空间结构,他们来复制父进程的虚拟空间,但不为这些段分配实际的物理空间与父进程共享只有当父子进程有更改相应段行为发生时才会为子进程相应的段分配物理空间。在这里插入图片描述

3、vfork()

  在vfork()函数使用时内核连子进程的虚拟空间地址都不用复制,而是直接共享了父进程的虚拟空间:
在这里插入图片描述
  写时拷贝是一种推迟甚至免除拷贝数据的技术,资源的复制只有在需要写入时才进行,在此前都是以只读的方式共享。传统的fork()系统调用直接把资源复制给新创建的进程,它的拷贝数据不会共享因此实现简单且效率低,如果新进程回去执行其他代码,则拷贝将变得没有意义。Linux的fork()使用写时拷贝(copy-on-write)页实现。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候。在页根本不会被写入的情况下—举例来说,fork()后立即调用exec()—它们就无需复制了。fork()的实际开销就是复制父进程的页表以及给子进程创建惟一的进程描述符。有序Unix强调进程快速执行力,因此这个优化变得重要。

巨人的肩膀:https://www.cnblogs.com/wuchanming/p/4495479.html

猜你喜欢

转载自blog.csdn.net/weixin_42647166/article/details/104791119
今日推荐