当我们从用户态转入到内核态时往往需要通过系统调用,在使用printf函数时,可能内部会调用一系列其他函数来到达对操作系统的调用接口。将printf封装这是库函数,方便我们进行使用,在printf中会有一个write()函数,此时通过write系统调用的接口进入内核态,内核态中同样也有write函数,此函数里面会出现out或者in操作。这就达到了对于io设备的操作
用户如何从用户态进入内核态???
在linux中通过80中断,或是syscall汇编指令进入。
在陷入系统调用时在离开用户态需要进行以下操作:
1.将调用的参数保存到寄存器中以便传递给内核态,最多6个参数
2.根据调用的方法来获取系统调用号,因为在系统调用程序时需要通过系统调用表(操作系统初始化时确定的)来决定调用具体哪一个方法。将系统调用号通过寄存器传递给内核态
3.触发80中断,此时pc的值指向系统调用中断服务程序的基地址。
在进入内核态时需要进行的操作:
1.将用户态寄存器的地址保存到pt_regs中
2.在调用表中根据调用号找到对应的函数
3.返回值写入pt_regs中
4.iret指令:可以根据pt_regs里面的值进行用户态程序的恢复
下面两图为完整的流程:
离开用户态进行的操作:
进入内核进行的操作:
64位系统调用和32位类似,64位通过syscall汇编指令可以为特殊寄存器直接赋值为系统调用服务程序的基地址。