转载:http://blogold.chinaunix.net/u2/66321/showart_725988.html
解释得非常帅气!
最近几本关于 L 的书,想来通络一下。也干了近几件疯狂的事情,想想都要偷着自娱自乐一番,真是无聊到尽头了,也就是另一番风景。有些你以前一直巴巴的信仰为真的东西,偶乐改变一下,结果发现,原来不是那个理,换个道也没什么比以前差的,丫,这样,也不错。
打算写十辨十析,罗罗一大堆,写些什么呢,想来想去,还是写些基础的东西吧, 希望这些基础的东西对朋友们理解其它方面能有个帮助 。这个专题的思想: what ? why ? how ? 总之要从根基上讲清楚,重点在原理上了。对了图作的不精,请大家谅解。
这三个方法是大佬 L 用 于创建子进程的三种方法。其实理解它们,要有一个实现上的意识即:进程->虚拟地址空间->物理地址空间即真实的存储。用户进程能感知的是进程的虚拟地址 空间,而虚拟地址空间->物理地址空间则由底层的内核来帮你实现。一个进程在地址空间上的表现形式就是:正文段,数据段,堆,栈。嗯,主要就是这四个部 分,内核为其分配相应的数据结构来表示它们,其看做是进程在地址空间的实体,也可以想象为灵魂。随后内核会为这四部分分配相应的载体,即真正的物理存储, 就像灵魂要附之于身体一样,那么,这些物理存储就是进程的真正实体的,我们称之为身体。那么这三个方法有什么不同呢?
ok ,现在有一个父进程 P1 ,这是一个主体,那么它是有灵魂也就身体的哦。现在在其虚拟地址空间(有相应的数据结构表示)上有:正文段,数据段,堆,栈这四个部分,相应的,内核要为这四个部分分配各自的物理块。即:正文段块,数据段块,堆块,栈块。至于如何分配,这是内核去做的事,在此不详述。
1. 现在 P1 用 fork() 函数为进程创建一个子进程 P2 ,内核:( 1 )复制 P1 的正文段,数据段,堆,栈这四个部分,注意是其内容相同。( 2 )为这四个部分分配物理块, P2 的:正文段-> PI 的正文段的物理块,其实就是不为 P2 分配正文段块,让 P2 的正文段指向 P1 的正文段块,数据段-> P2 自己的数据段块(为其分配对应的块),堆-> P2 自己的堆块,栈-> P2 自己的栈块。如下图所示:同左到右大的方向箭头表示复制内容。
图1
2.
写时复制技术:内核只为新生成的子进程创建虚拟空间结构,它们来复制于父进程的虚拟究竟结构,但是不为这些段分配物理内存,它们共享父进程的物理空间,当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间。
图2
3.
vfork()
:这个做法更加火爆,内核连子进程的虚拟地址空间结构也不创建了,直接共享了父进程的虚拟空间,当然了,这种做法就顺水推舟的共享了父进程的物理空间。
图3
通 过以上的分析,相信大家对进程有个深入的认识,它是怎么一层层体现出自己来的,进程是一个主体,那么它就有灵魂与身体,系统必须为实现它创建相应的实体, 灵魂实体与物理实体。这两者在系统中都有相应的数据结构表示,物理实体更是体现了它的物理意义。呵呵,说了这么多,其实系统之所以提供这三个方法,也都是 从实现效率上来考虑的,一般 fork 后要 exec ,所以很多父进程的数据对于子进程来说都是不需要的,后两种方法就是大佬 L 区别于 Unix 的一个主要特征,也可以说是其高明处之一吧,其创建进程特别的高效,怎么高效,通过以上的比较与分析,相信大家也能明白个五六了吧。