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

linux下fork系统调用的实现

2017-07-23 21:39 239 查看



今天再来写一篇,

本文章是在研究了linux-2.6.11版本的内核源码写的,其他版本可能存在差异。

一. fork()函数从用户态到内核态的过程

     1. 基本名词

     用户空间:虚拟地址空间中较低的3G字节(从虚拟地址 0x00000000到0xBFFFFFFF),供各个进程使用,称为“用户空间。

     内核空间:虚拟地址空间中最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为“内核空间”。

     用户态:当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。此时处理器在特权级最低的(3级)用户代码中运行,用户栈。

     内核态;当一个任务(进程)执行系统调用而陷入内核代码中执行时,就称进程处于内核运行态(内核态)。处理器便处于特权级最高的(0级)内核代码中执行,内核栈。

     2. 此过程的实现机制  —— 中断

           (1). 中断:在运行一个程序的过程中,继续以“插入”的方式执行一些完成特定功能的程序段的处理方式。

           (2). 分类:

                   A. 按照中断源(发出中断请求的设备)不同分为:

                        a. 内中断:程序运行错误引起的中断。

                        b. 外中断:外部设备,接口卡引起的中断。   

                        c. 软件中断:程序中语句引起的中断程序的执行。

                   B. 按照允许/禁止(开/关)中断分为;

                        a.  可屏蔽中断:可被cpu通过指令限制某些设备发出中断请求的中断。

                        b. 不可屏蔽中断:不允许屏蔽的中断。

                   C. 中断允许触发器:

                        a. 开中断指令:中断触发器置1。

                        b. 关中断指令:中断触发器置0。

          系统调用为0x80中断。

     3. 用户态到内核态过程图



      4. 结合源码进行说明如下:

                 (1) 通过系统调用号宏以及_syscal()l函数结合cpu寄存器和0x80中断从用户空间到内核空间。

 



                  (2)进入内核空间之后,通过system_call对eax寄存器中的系统调用号以及其他寄存器传入的参数进行保存(SAVE ALL),并通过sys_call_table系统调用表进行查询找

                      到内部系统调用函数sys_fork(),调用完后,将返回值通过eax寄存器带回用户态,然后RESTORE_ALL,将各个寄存器的值pop.

 



二. fork()函数在内核中的实现如图;

      1.  从sys_fork()  ---> do_fork(),   再通过copy_process()等函数以及语句实现。



      2.  了解一下struct  pt_regs  以及 struct  thread_info这两个结构体的成员变量以及作用能更好的理解fork()函数的内核实现。如果想更好的通透的理解,

          建议再把struct task_struct  拿出来研究一下,会对理解fork()有很大的帮助。

 


以上就是我根据自己想法总结的fork()系统调用的调用过程。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息