3.1 系统调用

系统调用是受控的内核入口

  • 系统调用将CPU从用户态切换到内核态,以便CPU访问受保护的内核内存。
  • 系统调用的组成是固定的,每个系统调用由一个唯一的数字标识。
  • 每个系统调用可辅之以一套参数,对用户空间与内核空间之间传递的信息进行规范。

系统调用过程

  1. 应用程序通过调用C语言函数库中的外壳函数(wrapper)来发起系统调用。
  2. 通过堆栈,参数传入外壳函数;内核希望参数置入特定寄存器,于是外壳函数将上述参数复制到寄存器
  3. 内核要区分每个系统调用,为此,外壳函数将系统调用编号复制到%eax中。
  4. 外壳函数执行中断机器指令(int 0x80),印发处理器从用户端切换到内核态,并执行系统中断向量指向的代码。
  5. 为响应中断0x80,内核调用system_call()例程(位于汇编文件arch/i386/entry.S中)处理该中断:

    1. 在内核中保存寄存器值;
    2. 审核系统调用编号的有效性;
    3. 以系统调用编号对存放所有调用服务例程的列表(内核变量sys_call_table)进行索引,发现并调用相应的例程;
    4. 从内核栈中恢复各寄存器值,并将系统调用返回值置于栈中
    5. 返回到外壳函数,同时处理器切换回用户态。
  6. 若系统调用的返回值有误,外壳函数会使用该值设置全局变量errno。然后外壳函数返回调用程序,并返回一个整形值,表明系统调用是否成功。

image.png