http://linux.chinaunix.net/bbs/thread-1051510-1-1.html
前面已经谈了内核加载与系统引导过程,下面我们来看看内核的 do_fork()
函数是如何创建一个新的进程的。
在 Linux 内核中,供用户创建进程的系统调用fork()函数的响应函数是
sys_fork()、sys_clone()、sys_vfork()。这三个函数都是通过调用内核函数 do_fork()
来实现的。根据
调用时所使用的 clone_flags 参数不同,do_fork() 函数完成的工作也各异。
这部分内容简单,我不打算就此而展开分析。下面我们重点来讲解以下 do_fork() 函数的工作原理。
我们知道 do_fork() 函数生成一个新的进程,大致分为三个步骤。
1、建立进程控制结构并赋初值,使其成为进程映像。这个过程完成以下内容。
在内存中分配一个 task_struct 数据结构,以代表即将产生的新进程。
把父进程 PCB 的内容复制到新进程的 PCB 中。
为新进程分配一个唯一的进程标识号 PID 和 user_struct 结构。然后检查用户具有执行一个新进程所必须具有的资源。
重新设置 task_struct 结构中那些与父进程值不同的数据成员。
设置进程管理信息,根据所提供的 clone_flags 参数值,决定是否对父进程 task_struct 中的指针 fs 、files 指针等所选择的部分进行拷贝,如果 clone_flags 参数指明的是
共享而不是拷贝,则将其计数器 count 的值加 1 ,否则就拷贝新进程所需要的相关信息内容 PCB 。这个地方是区分 sys_fork() 还是 sys_clone() 。
2、必须为新进程的执行设置跟踪进程执行情况的相关内核数据结构。包括 任务数组、自由时间列表 tarray_freelist 以及
pidhash[] 数组。
这部分完成如下内容:
把新进程加入到进程链表中。
把新进程加入到 pidhash 散列表中,并增加任务计数值。
通过拷贝父进程的上、下文来初始化硬件的上下文(TSS段、LDT以及 GDT)。
3、启动调度程序,使子进程获得运行的机会。
这部分完成以下动作:
设置新的就绪队列状态 TASK_RUNING , 并将新进程挂到就绪队列中,并重新启动调度程序使其运行。
向父进程返回子进程的 PID,设置子进程从 do_fork() 返回 0 值。
下面就具体的 do_fork() 函数程序代码进行分析(该代码位于 kernel/fork.c 文件中)
int do_fork(unsigned long clone_flags,unsigned long stack_start,
struct pt_regs *regs,
{


加载中…