linux (和 unix )将进程的概念说的很大,而且很细,进程不再仅仅拥有一个执行流,而是有了一个容器,其实某种意义上它本身就是一个容器。 unix 传统将进程想成 了一个执行绪,概念真的就是如此简单,简单的东西往往是好的东西,复杂的反而会更加糟糕。进程概念的简单性使得 fork 可以如此美妙如此简单的实现,使得 创建一个可执行映像可以分为 fork 和 exec ,正如我的前文所述。更加重要的是,传统 unix 将执行绪和执行过程中需要的资源分开了,如此就可以将资源 作为一件物品在进程之间传递,这丝毫没有问题。
linux 继承了 unix 一切好的东西,它的进程由 task_struct 表示,内部有很多表示资源的字段,比如 files_struct 表示打开的文 件, unix 中的 fork 的意义就是进程复制,复制是如此的简单且直观,使得你只需要复制当前的一切就可以了,复制往往比创造要简单得多,就像我们小的时 候总喜欢抄作业一样,后来又有了写时复制,更加节约了时间增加了效率,于是 fork 的意义就是复制一切资源,而对于执行绪内部的资源比如地址空间采取写时 复制的策略。因此,文件描述符作为打开文件的索引其实也是一种资源,这样的话在 fork 的时候就可以传递给子进程了。 linux 就是这样像叉子一样不断的 fork 最终形成一片天地。
linux 一向以地址空间的隔离作为其安全的根本,但是为何却可以拿资源传来传去呢?地址空间不也是一种资源吗?互相传递资源不会引起不安全吗?当然不会 不安全, linux 的进程结构设计的非常好,资源的共享完全在可控范围内,也就是说你可以选择传递或者不传递,一切由你决定,如果出了问题就是你自己造成 的而不是操作系统造成的。内核当然知道什么东西是可以安全传递的,比如文件描述符,该描述符对应的文件可以被子进程随意读写,而且文件描述符可以不变,对 于地址空间,它是进程的根本,在 fork 的时候是完全复制的(现在是写时复制),其实地址空间和文件描述符都是资源,那为什么内核对待它们的态度却不同 呢?对于文件描述符的复制是浅拷贝而对于地址空间的拷贝却是深拷贝, why ?这就涉及到一个资源性质的问题。我们看一下文件和地址空间作为资源有何不同, 其实很容易就可以看出它们的不同,对于文件是共享资源,它并不是进程的内禀属性,进程可拥有可不拥有,因此它当然可以被共享,而对于地址空间,它是进程的 内禀属性,进程的定义中明确规定地址空间不能和别的进程共享,因此它就必须被进程独享,因此在 fork 的时候要深拷贝。举个例子,丈夫这个定义,它表示此 人拥有一个妻子,妻子就是他的一个资源,而且他也可以拥有一支钢笔,但是对于丈夫而言妻子是他的内禀属性,因此妻子是他独有的,但是钢笔和丈夫并没有必然 关系,因此钢笔是可以让别人用的。