LINUX下系统调用执行过程

      通过软件中断0x80,系统会跳转到一个预设的内核空间地址,它指向了系统调用处理程序(不要和系统调用服务例程相混淆),即在arch/i386/kernel/entry.S文件中使用汇编语言编写的system_call函数。很显然,所有的系统调用都会同一跳转到这个地址进而执行system_call函数,那么system_call函数又该如何派发它们到各自的服务例程呢? 

  软中断指令int 0x80执行时,系统调用号会被放进eax寄存器,同时,sys_call_table每一项占用4个字节。这样,system_call函数可以读取eax寄存器获得当前系统调用的系统调用号,将其乘以4天生偏移地址,然后以sys_call_table为基址,基址加上偏移地址所指向的内容即是应该执行的系统调用服务例程的地址。 

  另外,除了传递系统调用号到eax寄存器,假如需要,还会传递一些参数到内核,比如write系统调用的服务例程原型为: 调用write系统调用时就需要传递文件描述符fd、要写进的内容buf以及写进字节数count等几个内容到内核。ebx、ecx、edx、esi以及edi寄存器可以用于传递这些额外的参数。 

  正如之前所述,系统调用服务例程定义中的asmlinkage标记表示,编译器仅从堆栈中获取该函数的参数,而不需要从寄存器中获得任何参数。进进system_call函数前,用户应用将参数存放到对应寄存器中,system_call函数执行时会首先将这些寄存器压进堆栈。 

  对于系统调用服务例程,可以直接从system_call函数压进的堆栈中获得参数,对参数的修改也可以一直在堆栈中进行。在system_call函数退出后,用户应用可以直接从寄存器中获得被修改过的参数。 

 

   系统调用通过软中断0x80陷进内核,跳转到系统调用处理程序system_call函数,并执行相应的服务例程,但由于是代表用户进程,所以这个执行过程并不属于中断上下文,而是处于进程上下文。  

posted @ 2012-02-28 23:21  only_eVonne  阅读(2719)  评论(0编辑  收藏  举报