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

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

2017-04-02 20:52 274 查看
黄二玉+ 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

进程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。当一个程序存放在储存介质上的时候,它只是一个指令,数据及其组织形式的描述。操作系统可以将一个程序加载到内存中以一个进程的形式运行起来,这就是这个程序的一个运行实例。所以我们也是可以多次加载一个程序到内存中,形成该程序的多个独立的运行实例。一个进程的内容不单只是程序的执行指令,还包括了诸如打开的文件,等待的信号,内部内核数据,处理器状态,内存地址空间及内存映射等等的资源。

进程的复制

系统进程复制通常使用clone()、fork()以及vfork()系统调用。do_fork()函数负责处理clone()、fork()和vfork()系统调用,也就是说,无论是clone()、fork()还是vfork(),都会调用do_fork()函数。do_fork()函数会调用copy_process()函数进行复制进程

进程的数据结构



进程的数据结构定义在/include/linux/sched.h(版本linux-3.18.6,1235行开始)中,是一个相当大的数据结构,里面包含有其他数据结构。

使用gdb追踪fork调用

在sys_fork,sys_clone,do_fork,copy_process,ret_from_fork打上一个断点



gdb并没有再sys_fork上捕捉到,而是在sys_clone上被捕捉到了



上面是do_fork,copy_process,ret_from_fork的断点情况

frok调用的过程



fork系统调用的调用过程简单描述如下:

1.首先是开始,父进程调用 fork ,因为这是一个系统调用,所以会导致 int 软中断,进入内核空间;

2.内核根据系统调用号,调用 sys_fork系统调用,而 sys_fork 系统调用则是通过 clone 系统调用实现的,会调用 clone 系统调用;

3.clone 系统调用的参数有一系列的标志用来标明父子进程之间将要共享的内容,这些内容包括虚拟内存空间,文件系统,文件描述符等。

4.在 clone 函数中,将会调用 do_fork,这个函数是 fork 的主要执行部分。在 do_fork 中,首先做一些错误检查工作和准备复制父进程的初始化工作。然后 do_fork 函数调用 copy_process。

5.copy_process 是对父进程的内核状态和相关的资源进行复制的主要函数。然后 copy_process 会调用 copy_thread 函数,复制父进程的执行状态,包括相关寄存器的值,指令指针和建立相关的栈;

6.copy_thread 中还干了一件事,就是把0值写入到寄存器中,然后将指令指针指向一个汇编函数 ret_from_fork 。所以在子进程运行的时候,虽然代码和父进程的代码是一致的,但是还是有些区别。在 copy_thread 完毕后,没有返回到 do_fork ,而是跳到 ret_from_fork ,进行一些清理工作,然后退出到用户空间。用户空间函数可以通过寄存器中的值得到 fork 系统调用的返回值为0。

7.copy_process 将会返回一个指向子进程的指针。然后回到 do_fork 函数,当 copy_process 函数成功返回的时候,子进程被唤醒,然后加入到进程调度队列中。此外,do_fork 将会返回子进程 的 PID;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: