图 2. 进程 A 运行代码
在 Unix 中,fork() 系统调用(之所以有这个名称,是因为它是一个调用或请求,要求操作系统进行协助)被用来产生新的进程。当程序 A (Program A) 执行指令 13 (Instruction 13) fork() 时,系统会立即创建进程 A 的一个精确克隆版本,并将其命名为进程 Z (Process Z)。Z 具有和 A 相同的环境变量、相同的内存内容、相同的程序状态,打开的文件也一样。图 3 显示的是进程 A 生成进程 Z后,进程 A 和 Z 的状态。
图 3. 进程 A 生成自身的克隆体
起初,进程 Z 是从进程 A 停止的地方开始执行的。也就是说,此后进程 Z 从指令 14 (Instruction 14) 处开始执行。进程 A 会在同一指令位置继续执行。
一般来说,指令 14 处的编程逻辑将测试当前的进程是子进程还是父进程,也就是说,进程 Z 和进程 A 中的指令 14 分别判定这两个进程是否为其他进程的后代或祖先。为了以示区别,fork() 系统调用在子进程中返回 0,但返回给父进程的却是进程 Z 的进程 ID。
在上次测试之后,进程 A 和进程 Z 会出现差异,每个进程会采用单独的代码路径,就像路上出现岔道,每一个都会走上不同的分枝。生成一个新进程的流程更多地被称为分叉,这就像两位旅行者走到了路上的岔道。因此,系统调用被命名为 fork()。
在分叉之后,进程 A 可能会继续运行同一个应用程序。而进程 Z 则可能立即发生变化,转到另一个应用程序。后一种操作会改变程序通过进程运行的内容,它被称为执行,但您可以把它看成是一次再生过程:虽然进程 ID 不变,但进程内部的指令会被新程序的指令完全取代。图 4 显示的是稍后进程 Z 的状态。
标签: