系统调用

API和系统调用的区别

  1. 都是函数
  2. API提供用户态服务或者内核态服务
  3. 系统调用通过软中断进入内核态
  4. API可能调用几个系统调用
  5. 系统调用也是一种API

int指令

  1. 用户态进程发出int $0x80指令(老版本Linux中,从用户态切换到内核态的唯一方法)
  2. 系统调用号放入eax寄存器
  3. 根据idtr寄存器找到IDT表,根据0x80找到对应门描述符
  4. 段级检查:将CPU的当前特权级CPL和门描述符中的段选择符的DPL比较(最低两位),CPL≥DPL
  5. 门级检查:将CPU的当前特权级CPL和门描述符的DPL比较,CPL需≤DPL。系统调用门的DPL=3,为了能让CPL=3的用户态进程调用这个异常处理程序
  6. 检查是否发生特权级变化。门描述符中的段描述符的DPL为0,CPL=3,需要进行用户栈到内核栈的更换。从TSS中取出内核栈的SS:ESP完成更换
  7. 将用户栈的SS:ESP压入内核栈(如果特权级没有变化,就不需要压入),将EFLAGS寄存器(标记程序的一些状态的寄存器,比如是否屏蔽中断)压入内核栈,再将被中断进程的CS:EIP压入内核栈
  8. 把门描述符中的段选择符和偏移值放入CS:EIP,CPU就跳转到系统调用处理程序system_call
  9. 调用SAVE_ALL把剩余的寄存器也压入内核栈
  10. 根据EAX中的系统调用号在系统调用表找到对应表项,获取相应的系统调用服务例程的指针,内核就找到要调用的系统调用服务例程
  11. 当从系统调用服务例程结束时,返回值在EAX中,并用返回值更新内核栈中的EAX
  12. 调用RESTORE_ALL恢复保存在内核栈中的寄存器的值
  13. 执行iret回到用户态
posted @ 2021-02-08 22:18  肥斯大只仔  阅读(73)  评论(0编辑  收藏  举报