您的位置:首页 > 运维架构 > Linux

Linux0.11进程创建函数fork()

2011-02-20 11:03 731 查看



在Linux中,有一个特殊的函数fork()。这个函数会向父进程返回
子进程的进程号PID,而向子进程返回0。有没有想过一个函数怎么可能有两个不同的返回值呢?在Linux0.11中,每个进程都有一个进程控制块结构
task_struct。系统支持最多64个进程,定义在全局数组task中。其中进程0为初始进程,其它所有的进程都是通过fork产生的。用户态的
fork函数最终调用系统调用sys_fork()。sys_fork()系统调用分成2步完成,第一步调用函数
find_empty_process(),在task数组中找一项空闲项;第二步调用copy_process()函数,复制进程。

对所有fork()调用产生的进程,通过递增并循环的方式为其分配进程号。有一个全局变量last_pid用来记录上次使用的进程号:

long last_pid=0;

在find_empty_process中,不断递增last_pid,寻找第一个未被其它进程使用的进程号作为新进程的进程号。如果递增后的脂出正数表示范围,则重新从1开始。


程控制块中还保存有进程的任务状态段数据结构tss,用于存储处理器管理进程的所有信息。也就是说,在任务切换过程中,首先将处理器中各寄存器的当前值被
自动保存当前进程的tss中;然后,下一进程的tss被加载并从中提取出各个值送到处理器的寄存器中。由此可见,通过在tss中保存任务现场各寄存器状态
的完整映象,实现任务的切换。

struct tss_struct tss;

因此,一旦在task数组中找到空闲项和
进程号,我们就可以为该进程的进程控制块结构申请一个页面的内存。这个工作是在copy_process()函数中完成的。当然
copy_process()函数的最主要的任务是为子进程复制父进程信息,并设置子进程的任务状态段,其中最关键的两步是:

1. 把子进程tss中的eip设置为父进程系统调用返回地址,这样当子进程被调度程序选中后,将从父进程的fork()返回地址处开始执行。

p->tss.eip = eip;

2. 把
子进程tss中的eax设置为0,而eax是存放函数返回值的地方,这样子进程中返回的是0。注意子进程并没有执行fork()函数,子进程的系统堆栈没
有进行过操作,当然不会有像父进程那样的fork函数调用。但是当子进程开始运行时,就好像它从fork中返回。

p->tss.eax = 0;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: