系统调用的初始化过程与系统调用执行过程

来源:互联网 发布:福建省人口普查数据 编辑:程序博客网 时间:2024/05/03 12:27

刘昆

  + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”


本文首先介绍系统调用的初始化过程,其次已getpid()函数为例,介绍系统调用的执行过程。


系统调用初始化过程:

1、在start_kernel时,由trap_init()处完成初始化,//start_kernel实现细节位于$(kernel_root)/init/main.c

2、在trap_init()中,set_system_trap_gate(SYSCALL_SECTOR,&system_call)将系统处理函数与异常向量关联并注册

(即建立软中断入口:

asm{

     ……

“int 0x80 \n\t"

……

}

//trap_int()实现细节与CPU相关,位于$(kernel_root)/arch/$(cpu)/kernel/traps.c


系统调用执行过程:

以getpid()函数使用为例,先看一下测试代码:

#include <stdio.h>

#include <unistd.h>

/*

    库函数:pid_t getpid(void)

    该函数返回值为当前进程的进程号,系统调用号为20

    通过内嵌汇编证明手动使用相关系统调用号进入内核进程,

    getpid()系统自动使用相关系统调用号进入内核进程效果一样

 */

int main(){

    intvolatile pid,pid_asm;

    pid = getpid();

    printf("pid = %u\n",pid);

    asmvolatile(

    "movl $0,%%ebx\n\t"

    "movl $20,%%eax\n\t"  //%%eax存放系统调用号

    //产生异常号128,调用软终端进入内核,内核中系统调用表中值匹配%eax值,拿出内核sys_getpid()等的内核函数指针,并进入内核态执行,执行结果最后放入%eax

    "int $0x80\n\t"

    "movl %%eax,%0\n\t"

    :"=m"(pid_asm)

    );

    printf("pid_asm = %u\n");

}

这段代码用内嵌汇编代码手动模拟了getpid()函数的系统调用效果,其中%eax传递系统调用号(常量),%ebx传递函数参数,因为getpid()是无参函数,故%ebx置0:

1、int $0x80  :进入软中断,中断处理函数由异常向量0x80指定;

2、进入system_call函数 //函数实现细节位于$(root_direc)/arch/$(cpu)/kernel/entry_32.S

3、pushl %eax保存系统调用号0x14;

4、SAVE_ALL保存堆栈上下文环境,进入内核上下文环境

5、系统调用号有效性检查等

6、将系统调用号与syscall_table内容遍历匹配,调用对应的内核处理函数sys_getpid,   //syscall_table位于$(root_direc)/arch/$(cpu)/kernel/syscall_table_32.S

7、sys_getpid()处理结束后,存储返回值

8、进入系统调用返回环节:函数参数处理

9、恢复用户态堆栈上下文

10、退出终端状态


0 0