窥探 kernel --- 系统调用过程分析



本系列文章由张同浩编写,转载请注明出处:http://blog.csdn.net/muge0913/article/details/7518568

邮箱:muge0913@sina.com






过程分析:

1、系统调用需要一个用户空间到内核空间的转换,不同的平台有不同的指令来完成这样的转换,这个指令也叫做操作系统陷入(operating systemtrap)指令。在linux中对于x86来说是用软中断0x80,也即是int $0x80。软中断由软件指令触发,硬中断由硬件触发。

通过软中断,系统会跳到一个预定的内核空间。它指向了系统调用处理程序(不是系统调用服务程序)system_call函数(arch/x86/kernel/entry32.h)。如上图。


2、system_call到服务程序

显然所有的系统调用都会跳到这个地址执行system_call函数。在执行int 0x80时系统调用号会被放入eax寄存器中。因为sys_call_table每个项占用4个字节。所以sys_call_table作为基地址,eax*4作为偏移量就可以找到对应的服务程序的地址。

系统调用的参数通过其他寄存器来传递。如


  1. write(unsignedint fd,const char *buf,size_t count)  
write(unsignedint fd,const char *buf,size_t count)

寄存器ebx,ecx,esi,edx来传递。但是前面我们说过,asmlinkage表示内核从堆栈中提取参数,而不是寄存器。因为在system_call执行时首先把这些寄存器压入堆栈了。从下面的代码中就可找到答案~~~

  1. ENTRY(system_call)  
  2.   
  3.      RING0_INT_FRAME             # can't unwind into user spaceanyway  
  4.   
  5.      pushl_cfi%eax              # save orig_eax  
  6.   
  7.      SAVE_ALL  
  8.   
  9.      GET_THREAD_INFO(%ebp)  
  10.   
  11.                        #system call tracing in operation / emulation  
  12.   
  13.      testl$_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)  
  14.   
  15.      jnzsyscall_trace_entry  
  16.   
  17.      cmpl$(nr_syscalls), %eax  
  18.   
  19.      jaesyscall_badsys  
  20.   
  21. syscall_call:  
  22.   
  23.      call*sys_call_table(,%eax,4)  
ENTRY(system_call)

     RING0_INT_FRAME             # can't unwind into user spaceanyway

     pushl_cfi%eax              # save orig_eax

     SAVE_ALL

     GET_THREAD_INFO(%ebp)

                       #system call tracing in operation / emulation

     testl$_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)

     jnzsyscall_trace_entry

     cmpl$(nr_syscalls), %eax

     jaesyscall_badsys

syscall_call:

     call*sys_call_table(,%eax,4)



系统服务程序从堆栈中获取参数,并修改,最后再通过堆栈返回修改后的数值。

不是所有的系统调用都有实际内容,如sys_ni_syscll在kernel/sys_ni.c中定义:

  1. asmlinkage long sys_ni_syscall(void){  
  2.   
  3. return -ENOSYS;  
  4.   
  5. }  
asmlinkage long sys_ni_syscall(void){

return -ENOSYS;

}



你会发现在sys_call_table中sys_ni_syscall占据了很多内容,其实它代表着已被淘汰的系统调用。

  1. .longsys_ni_syscall   /* old stty syscallholder */  
  2.   
  3. .longsys_ni_syscall   /* old gtty syscallholder */  
  4.   
  5. .longsys_access  
  6.   
  7. .longsys_nice  
  8.   
  9. .longsys_ni_syscall   /* 35 - old ftime syscallholder */  
  10.   
  11. .longsys_sync  
  12.   
  13. .longsys_kill  
  14.   
  15. .longsys_rename  
  16.   
  17. .longsys_mkdir  
  18.   
  19. .longsys_rmdir        /* 40 */  
  20.   
  21. .longsys_dup  
  22.   
  23. .longsys_pipe  
  24.   
  25. .longsys_times  
  26.   
  27. .longsys_ni_syscall   /* old prof syscallholder */  
     .longsys_ni_syscall   /* old stty syscallholder */

     .longsys_ni_syscall   /* old gtty syscallholder */

     .longsys_access

     .longsys_nice

     .longsys_ni_syscall   /* 35 - old ftime syscallholder */

     .longsys_sync

     .longsys_kill

     .longsys_rename

     .longsys_mkdir

     .longsys_rmdir        /* 40 */

     .longsys_dup

     .longsys_pipe

     .longsys_times

     .longsys_ni_syscall   /* old prof syscallholder */

如上面可知sys_ni_syscall代替了不用的stty和gtty和prof。其实只要是被内核淘汰的系统调用都会被sys_ni_systcall代替。之所以这样是为了老的程序在新的内核上运行时不至于出现大的问题。如不应调用这个系统调用却调用了那个系统调用了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值