linux: 系统调用

 

浅析linux中open系统调用 http://www.embedu.org/Column/Column465.htm

  1. linux open系统调用过程简要概括:

  在linux应用程序中,调用open("dir/filename" , O_RDWR);

  看x86汇编结果是 call open, 即是说跳到系统调用 CALL(sys_open)处.    // arm的系统调用在arch/arm/kernel/calls.S 

  之后的执行路径如下: sys_open ---> do_sys_open ---> do_filp_open ---> do_last---> nameidata_to_filp ---> __dentry_open.

  在__dentry_open中, 是这样调用我们驱动里面file_operation里面书写的open的:

    if (!open && f->f_op)
        open = f->f_op->open;
    if (open) { //如果我们驱动里面file_operation里面open有定义,就调用,没定义就跳过.
        error = open(inode, f);
        if (error)
            goto cleanup_all;
    }

 

2. 以字符设备的驱动为例,分析系统调用的执行过程,内核版本为 linux-2.6.22.6

2.1. 用户空间到内核的转换

  系统调用需要一个从用户空间到内核空间的转换,不同平台转换的指令不同,这种特定的指令称作操作系统的陷入(operating system trap)。

  X86结构中使用软中断x080来实现。即汇编指令 int $0x80.通过软中断0x80 ,系统就会跳到一个预设的内核空间地址。它指向系统调用处理程序system_call,在arch/x86/kernel/entry_32.S 中以汇编语言编写,该过程主要有2个步骤。

    

(1)系统启动时,对INT 0x80进行一定的初始化。

使用汇编子程序setup_idt(arch/i386/kernel/head.S)初始化idt表(中断描述符表),这时所有的入口函数偏移地址都被设为ignore_int

(2)设置中断描述符表

start_kernel函数中(init/main.c)调用trap_init()(arch/x86_64/kernel/traps.c)函数,设置中断描述符表。在trap_init()该函数里,实际上是通过调用函数 set_system_trap_gate(SYSCALL_VECTOR, &system_call);来完成该项的设置的。其中的SYSCALL_VECTOR就是0x80,而system_call则是一个汇编子函数,它即是中断0x80的处理函数,主要完成两项工作:寄存器上下文的保存、跳转到系统调用处理函数。

 

2.2. syscall_call函数到系统调用服务例程:在上面执行软终端0x80时,系统调用号会被放入eax寄存器,system_call()函数读取 eax寄存器获取当前系统调用的调用号。然后将其乘以4生成偏移地址,然后再以sys_call_table为基址。基址+偏移地址=>系统调用服 务例程的地址。其中sys_call_table基址在文件arch/x86_64/kernel/entry.S 中定义。同时 table表中每一项例程的地址占用4个字节,所以上面乘以4。

到这儿system_call()就到服务例程的地址了。然后另一个问题-参数传递需要解决。

由于系统调用例程在定义时时用 asmlinkage 标记了的,所以编译器仅从堆栈中获取该函数的参数。在进入system_call函数前,用户应用会把参数存放到寄存器中,system_call函数执 行时会首先把这些寄存器压入堆栈。这样对系统调用服务例程可以直接从堆栈照片能够获取参数。

2.3. 系统调用函数的执行

  sys_open ---> do_sys_open ---> do_filp_open ---> do_last---> nameidata_to_filp ---> __dentry_open.

 

当然,在VFS层中对open函数的操作远不止上文描述的这么简单,会进行权限和打开方式的判断等。普通的驱动开发者很少涉及对这部分代码的修改,主要还是学习和欣赏Linux内核。

 

感谢华清远见吴老师的分享.

posted @ 2016-07-05 00:12  oucaijun  阅读(401)  评论(0编辑  收藏  举报
下载TeamViewer完整版 下载TeamViewer