相关技术要点:
- 时空错配-Copy On Write
(1) 了解虚拟内存
物理内存是系统硬件提供的内存大小,是真正的内存,相对于物理内存,在Linux下还有一个虚拟内存的概念。虚拟内存的存在就是为了满足物理内存的不足而提出的策略,它利用磁盘空间虚拟出的一块逻辑内存。用作虚拟内存的磁盘空间被称为交换空间。
进程中看到的地址都是逻辑地址;
虚拟内存提供的三个重要的能力:
1) 它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,根据需要在磁盘和主存之间来回传送数据,使得能够运行比内存大的多的进程。
2) 它为每个进程提供了一致的地址空间,从而简化了存储器管理;
3) 它保护每个进程的地址空间不被其他进程破坏 ;
(2)写时拷贝技术
传统的fork系统调用直接把所有的资源复制给新创建的进程。这种实现过于简单并且效率低下,因为它拷贝的数据也许并不共享,更糟糕的情况是,如果新进程打算立即执行一个新的映像,那么所有的拷贝都将前功尽弃。
Linux的fork()使用写时拷贝页实现。写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。
只有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。也就是说,资源的复制只有在需要写入的时候才进行,在此之前,知识以只读方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候才进行。在页根本不会被写入的情况下(举例:fork()后立即调用exec())他们就无需复制了。
fork()的实际开销就是复制父进程的页表以及给子进程创建唯一的进程描述符。在一般情况下,进程创建后都会马上运行一个可执行的文件,这种优化可以避免拷贝大量根本就不会被使用的数据(地址空间里常常包含数十兆数据)。由于Unix强调进程快速执行的能力,所以这个优化是很重要的。
不采用写时拷贝技术,第一,复制开销比较大;第二,占用内存空间;
所以我们对fork复制进程的过程做了一个优化:———-写时拷贝技术。
引入了写时拷贝技术,就可以延迟页面的拷贝,甚至免除页面的拷贝
还有一个需要注意的地方:写时拷贝是以页为单位的,哪怕这个页中只有一个字节被修 改了,我们也需要将整个页面都复制出来一份
pid1 = fork()
pid2 = fork()
printf(“pid1:%d, pid2:%d”, pid2, pid2);
一共创建了四个进程
参考:
https://blog.csdn.net/weixin_59179454/article/details/127092115