分析Linux内核创建一个新进程的过程

“郭孟琦 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”


我承认这周课上完有一种崩溃的感觉,感觉难度陡然增加。仔细想想发现,其实难度来自于linux内核的结构庞杂。换一种思路,从大框上入手去分析新进程的创建过程效果会更好一些。


其次在调试过程中发现通过gdb确实可以验证程序的执行过程,但是仅凭gdb分析不是非常的清楚,因此我将精力放在了对源码的理解上。


在例子中是采用了fork系统调用来创建一个新进程。

从效果上看既执行了pid=0的部分,又执行了pid>0的部分。

显然fork返回了2次,对于父进程pid>0,子进程pid=0;


fork系统调用的系统函数是sys_clone,但本质上是执行了

do_fork

其中

p = copy_process(clone_flags, stack_start, stack_size,child_tidptr, NULL, trace);

就是将父进程的堆栈信息复制给子进程(也包含了为子进程在内存上申请空间作为子进程的堆栈)。

主要是通过这一句完成的

p = dup_task_struct(current);
而在copy_process接下来的部分是将父进程的 task_struct内容复制给子进程,其中包括了文件、内存、信号量、进程状态等信息的描述。(400多行的结构体也是开了眼了)链接:http://codelab.shiyanlou.com/xref/linux-3.18.6/include/linux/sched.h#1235


而我关注的主要部分是

retval = copy_thread(clone_flags, stack_start, stack_size, p);

在copy_thread中

p->thread.sp = (unsigned long) childregs;
调度后子进程堆栈的栈顶。

p->thread.ip = (unsigned long) ret_from_fork;
决定了子进程中调度后将从ret_from_fork处执行

childregs->ax = 0;
决定了子进程返回值(eax)为0;


这基本上就是课程所讲的内容,但是p和childregs的关系是什么?我对此探究了一下。

首先p是copy_thread的一个参数,这个p来自dup_task_struct()的返回值,同过回头对dup_task_struct()的分析发现p就是指向为子进程申请的task_struct。

而childeregs和p是在copy_thread()中通过

struct pt_regs *childregs = task_pt_regs(p);
#define task_pt_regs(t) (&(t)->thread.regs)
很显然childregs是p指向的PCB的一部分。

通过

*childregs = *current_pt_regs();
就实现了 将父进程堆栈的内容赋给了子进程。此时我认为子进程堆栈内容就是父进程调用SAVE_ALL后的堆栈内容。

那么子进程在调度后开始运行时就在

ret_from_fork;
处执行,进入
syscall_exit

就像执行完一次系统调用,在menu中子进程就会进入0那个部分然后屏幕输出。


总结:

Linux系统创建一个新进程的过程就是自我复制的一个过程。在启动内核的时候,start_kernel先产生1号进程(init)和2号进程(kthreadd),在1号进程中又fork出其他用户态进程,而start_kernel最终初始化完内核后变为0号进程(idle)。这三个进程是代码写出来的进程。其他的进程都是通过上面所写的“复制”“修改”“调度”这样产生出来的子进程。


这样创建新进程的方法在创建一个新进程时,父进程使用的内存并不是真正的全部复制给子进程。它们都指向同一处内存空间,但是把内存页面标记为copy-on-write。当任何一个进程试图向这些内存中写入内容时,就会产生一组新的内存页面由这个进程私有。这样,通过这种方法提高了创建新进程的效率,因为内存空间的复制推迟到了发生写操作的时候。


fork是用当前的进程来复制出一个新的进程,新进程与原进程一模一样,执行的代码也完全相同,但新进程有自己的数据空间、环境变量和文件描述符,我们通常根据fork函数的返回值来确定当前的进程是子进程还是父进程,返回一个pid_t的值用于判断,我们还可以继续执行fork后面的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值