int $0x80系统调用的idea

1、基础知识

     用户态和内核态

          一般现代CPU都有几种不同的指令执行级别,Linux总共划分为4个指令执行级别:内核运行在0级别上,1,2级别默认不运行,用户程序运行在3级别上。
          在内核指令执行级别上,代码可以执行特权指令,访问任意的物理地址。
          在用户指令执行级别上,代码的掌控范围会受到限制。只能在对应级别允许的范围内活动。
          cs寄存器的最低两位表明了当前代码的特权级:CPU每条指令的读取都是通过cs:eip这两个寄存器:其中cs是代码段选择寄存器,eip是偏移量寄存器。

         上述判断由硬件完成。

int $0x80系统调用的idea_第1张图片

          一般来说在Linux中,地址空间是一个显著的标志:0xc0000000以上的地址空间只能在内核态下访问,0x00000000-0xbfffffff的地址空间在两种状态下都可以访问。


2、int $80汇编指令

          I386CPU将用户空间程序限制在0-3G空间,将内核程序限制在3G~4G空间,这样就实现了用户空间和内核空间的隔离;
          程序的执行过程需要访问特定的系统程序以完成相应的功能。而用户程序运行在用户态,不能够访问特定状态下的系统程序。而用户程序又需要执行系统程序,这就促使int $80的产生:
          应用程序通过int 0x80(软中断)指令实现用户空间与内核空间的交互。CPU会把软中断做为陷阱来处理,所以软中断也称为编程异常,其中int 0x80可以用于执行系统调用。

3、int $80的执行功能

     Int $80主要实现对寄存器的压栈:
  1. 保存:SS:esp,CS:EIP,eflag中的内容到进程对应的内核堆栈;
  2. 修改:SS:esp内容改为system_call对应的的内核堆栈的基地址,CS:EIP:内容改为system_call的第一条指令的地址,eflag内容修改为新的标志。

    

          总而言之,int $0x80的就是在系统调用产生时,完成用户态到内核态的切换。由于用户进程在用户态执行和内核态需要对应不用的内核堆栈,所以再进行系统调用时,需要保存用户态最后的esp,eip等状态信息,以便于系统调用结束能够返回到发生系统调用的地址继续用户程序的执行,这就是int $0x80完成的对寄存器内容的保存。

          执行系统调用的时候,先把系统调用号保存到EAX寄存器中,然后执行int $0x80,然后转入system_call系统调用指令开始执行,system_call根据保存到system_call内核堆栈中的系统调用号的值,转为执行相应的系统调用处理函数。
Iret指令指int $0x80的逆过程,弹出int $0x80指令所产生的内容堆栈块的内容到对应的寄存器中,CPU把控制权有内核交给用户程序,执行状态回到用户态,用户程序继续执行。至此,系统调用,系统返回过程结束。

你可能感兴趣的:(int $0x80系统调用的idea)