本文只是自己学习总结,当然欢迎大家阅读,要想更好的了解系统调用以及windowsAPI(推荐去看程序员自我修养第12章)
系统调用的介绍:简而言之,就是用户写的程序进行调用内核中的方法。
用户程序没有权限直接进行访问多少系统资源的,因为由于系统的有限资源有可能被多个应用进程进行同时访问,所以如果不进行对系统资源的保护,那么各个应用程序难免会产生冲突。所以只能在内核的权限上才能访问系统资源,因为这时已经对访问系统资源的各个用户程序做了相应的控制。
首先来了解一下,Linux下的系统调用:
Linux X86体系下系统调用,都是通过0X80中断完成,各个寄存器传递参数,eax寄存器用于传递系统调用的接口号,当系统调用返回时,eax又传递系统调用的返回值。
**系统调用的弊端:**各个操作系统之间系统调用不兼容,导致程序的可移植性太差。所以存行库应运而生。
运行库:它相当于对系统调用的一层封装。介于用户程序和内核程序的一个中间层。它只包含不同体系的之间功能的交集(在此不详细讲解)
系统调用的原理:操作系统一般是通过中断来进行用户态到内核态的切换的。接下来介绍一下中断的概念。中断:一个硬件或者软件发出的请求,要求暂停当前的工作转手去做更重要的事情。例如:当你在编辑文本时,键盘被不断按下,键盘上的芯片发送给一个信号给cpu,cpu接到信号后,然后做出相应的请求即可。不同的中断,有对应的中断处理程序。中断和相应的处理程序时一一对应的。(在此不详细介绍如何处理的,下面会在举例中明示)
Linux所有的系统调用都是由0X80号中断触发的,i386下windows绝大多数系统调用都是由int 0x2e触发的。下面用直观的图示来表示liunux下系统调用的过程
触发中断:当执行到要调用系统调用的时候。以fork为例,其实是执行了下面的汇编代码:
fork:
mov eax ,2 将系统调用号写入eax寄存器
int 0X80 0X80中断
cmp eax,0XFFFFFF83
jb syscall_noerror
neg eax
mov errno ,eax
mov eax, 0XFFFFFFFF
syscall_noerrror:
ret;
当要进行的系统调用有参数时,通过其他寄存器来传值。linux支持的的系统调用参数有6个,分别通过:EBX ECX EDX ESI EDI EBP 来传参。
当到执行到int 0X80时,ios首先得保存现在运行的程序的各个状态以及数据,以便从内核中恢复到用户程序。再由用户态切换到内核态来执行内核代码。
在执行中断向量表中的0X80号中断前,cpu还要进行栈的切换。ESP所在栈空间就是当前栈,SS的值是指向当前栈所在的页。
切换堆栈:
(1) 用户栈----->内核栈: 保存当前的ESP SS的值 ,将ESP、SS的值设置为内核栈的相应值。
(2) 恢复原来的ESP SS的值。
在此需注意,(1)中保存的ESP SS 的值保存在内核上。
执行到0X80 处时,cpu除了切入内核态之外,还会做将以下两件事。
1> 找到当前进程的内核栈(每个进程都有自己的内核栈)
2> 在内核栈中依次压入用户的寄存器,(ESP SS EFLAGS CS EIP)的值。用来恢复用户态的状态。