你好,游客 登录 注册 搜索
背景:
阅读新闻

Linux系统调用过程

[日期:2012-07-19] 来源:cnblogs  作者:lknlfy [字体: ]

第9行,比较eax的值是否大于等于nr_syscalls,nr_syscalls是比最大有效系统调用号大1的值,在/arch/x86/kernel/entry_32.S中定义:

#define nr_syscalls ((syscall_table_size)/4)

其中syscall_table_size就是系统调用表的大小(单位:字节),syscall_table_size其实是一个数组,数组里存放的是各个系统调用函数的地址,元素类型是long型,除以4刚好是系统调用函数的个数。

如果从eax寄存器传进来的系统调用号有效,那么就执行第12行,在系统调用表里找到相应的系统调用服务程序,sys_call_table在/arch/x86/kernel/syscall_table_32.S中定义:

ENTRY(sys_call_table)
     .long sys_restart_syscall    /* 0 - old "setup()" system call, used for restarting */
     .long sys_exit
     .long ptregs_fork
     .long sys_read
     .long sys_write
     .long sys_open        /* 5 */
     .long sys_close
 .................

*sys_call_table(,%eax,4)指的是sys_call_table里偏移量为%eax*4上的那个值指向的函数,这里%eax=3,那么第5行的sys_read()函数就会被调用。sys_read()在/fs/read_write.c中定义:

SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
 {      
         struct file *file;     
         ssize_t ret = -EBADF;
         int fput_needed;
        
         file = fget_light(fd, &fput_needed);
         if (file) {
                 loff_t pos = file_pos_read(file);
                 ret = vfs_read(file, buf, count, &pos);
                 file_pos_write(file, pos);
                 fput_light(file, fput_needed);
         }
        
         return ret;
 }

可见,参数的形式和用户空间的一样。SYSCALL_DEFINE3是一个宏,在/include/linux/syscalls.h中定义:

#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)

SYSCALL_DEFINEx也是一个宏,也在此文件中定义:

#define SYSCALL_DEFINEx(x, sname, ...)                \
     __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
 .....
 #define __SYSCALL_DEFINEx(x, name, ...)                    \
    asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))
 ......

宏展开后,就是声明了这么一个函数:

asmlinkage long sys_read(unsigned int fd, char __user *buf, size_t count);

asmlingage是一个宏,定义为:__attribute__((regparm(0))),作用是让这个函数只从栈上获取参数(因为之前的SAVE_ALL将参数压到了栈里面)。

当执行完中断处理程序后,后面会调用RESTORE_REGS来恢复各个寄存器:

..............
     CFI_REMEMBER_STATE
     je ldt_ss            # returning to user-space with LDT SS
 restore_nocheck:
     RESTORE_REGS 4            # skip orig_eax/error_code
 ...............

第5行,RESTORE_REGS的定义:

.macro RESTORE_REGS pop=0
     RESTORE_INT_REGS
 1:    popl_cfi %ds
     /*CFI_RESTORE ds;*/
 2:    popl_cfi %es
     /*CFI_RESTORE es;*/
 3:    popl_cfi %fs
     /*CFI_RESTORE fs;*/
     POP_GS \pop
 .................

第2行,RESTORE_INT_REGS的定义:

.macro RESTORE_INT_REGS
     popl_cfi %ebx
     CFI_RESTORE ebx
     popl_cfi %ecx
     CFI_RESTORE ecx
     popl_cfi %edx
     CFI_RESTORE edx
     popl_cfi %esi
     CFI_RESTORE esi
     popl_cfi %edi
     CFI_RESTORE edi
     popl_cfi %ebp
     CFI_RESTORE ebp
     popl_cfi %eax
     CFI_RESTORE eax
 .endm

到这里差不多了,再对read()跟踪的话就会涉及文件系统方面的内容,以后会说的。

linux
相关资讯       Linux系统调用 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款