设为首页 加入收藏

TOP

Linux0.11进程创建函数fork()
2014-11-24 00:42:09 来源: 作者: 【 】 浏览:3
Tags:Linux0.11 进程 创建 函数 fork

在Linux中,有一个特殊的函数fork()。这个函数会向父进程返回子进程的进程号PID,而向子进程返回0。有没有想过一个函数怎么可能有两个不同的返回值呢?


#include
#include /* contains fork prototype */
int main(int argc, char **argv) {
if (fork() == 0) {
printf("I am the child process.\n");
} else {
printf("I am the parent process.\n");
}
}



在Linux0.11中,每个进程都有一个进程控制块结构task_struct。系统支持最多64个进程,定义在全局数组task中。


struct task_struct * task[NR_TASKS] = {&(init_task.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;


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇bochs模拟运行Linux0.11问题及解答 下一篇Linux kernel常用编码模式

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: