浅析linux中open系统调用
来源:互联网 发布:让子弹飞 知乎 编辑:程序博客网 时间:2024/05/21 01:53
从2.6.19的linux内核开始,内核的系统调用使用函数syscall,其函数原型为:int syscall(int number, ...)其中number是系统调用号,number后面应顺序接上该系统调用的所有参数。以x86平台为例,系统调用号在内核源码中的路径是/arch/x86/include/asm/unistd_32.h头文件中定义。其中大部分以__NR_开头,比如open的系统调用号是5。
本文以字符设备的驱动为例,分析系统调用的执行过程,内核版本为2.6.35.
1、用户空间到内核的转换
系统调用需要一个从用户空间到内核空间的转换,不同平台转换的指令不同,这种特定的指令称作操作系统的陷入(operating system trap)。X86结构中使用软中断x080来实现。即汇编指令 int $0x80.通过软中断0x80 ,系统就会跳到一个预设的内核空间地址。它指向系统调用处理程序system_call,在arch/x86/kernel/entry_32.S 中以汇编语言编写,该过程主要有2个步骤。
(1)系统启动时,对INT 0x80进行一定的初始化。
使用汇编子程序setup_idt(linux/arch/i386/kernel/head.S)初始化idt表(中断描述符表),这时所有的入口函数偏移地址都被设为ignore_int ,如下图所示。
(2)设置中断描述符表
start_kernel函数中(init/main.c)调用trap_init()(arch/x86/kernel/trap.c)函数,设置中断描述符表。在trap_init()该函数里,实际上是通过调用函数set_system_trap_gate(SYSCALL_VECTOR, &system_call);来完成该项的设置的。其中的SYSCALL_VECTOR就是0x80,而system_call则是一个汇编子函数,它即是中断0x80的处理函数,主要完成两项工作:寄存器上下文的保存、跳转到系统调用处理函数。
2、系统调用函数的入口
syscall_call函数到系统调用服务例程:在上面执行软终端0x80时,系统调用号会被放入eax寄存器,system_call()函数读取eax寄存器获取当前系统调用的调用号。然后将其乘以4生成偏移地址,然后再以sys_call_table为基址。基址+偏移地址=>系统调用服务例程的地址。其中sys_call_table基址在文件arch/x86/kernel/syscall_table_32.S中定义。同时table表中每一项例程的地址占用4个字节,所以上面乘以4。
到这儿system_call()就到服务例程的地址了。然后另一个问题-参数传递需要解决。由于系统调用例程在定义时时用 asmlinkage 标记了的,所以编译器仅从堆栈中获取该函数的参数。在进入system_call函数前,用户应用会把参数存放到寄存器中,system_call函数执行时会首先把这些寄存器压入堆栈。这样对系统调用服务例程可以直接从堆栈照片能够获取参数。
3、系统调用函数的执行
open会最终执行sys_open函数:
里面调用do_sys_open()函数:
在上图的L884行中,获取未被使用的文件描述符,在do_filp_open()函数中打开文件。其函数调用过程如下:
sys_open -> do_sys_open -> do_filp_open ->do_last-> nameidata_to_filp -> __dentry_open
4、驱动代码file_operations的调用
在 __dentry_open函数中:
L685中 open = f->f_op->open;即调用chrdev_open。
在file: fs/char_dev.c中static int chrdev_open(struct inode *inode, struct file *filp)调用ret = filp->f_op->open(inode,filp);即为真正的file_operations中的open函数。
当然,在VFS层中对open函数的操作远不止上文描述的这么简单,会进行权限和打开方式的判断等。普通的驱动开发者很少涉及对这部分代码的修改,主要还是学习和欣赏Linux内核。
- 浅析linux中open系统调用
- 浅析linux中open系统调用
- Linux系统调用浅析
- 浅析Linux系统调用
- linux 系统调用浅析
- 浅析 Linux 系统调用
- linux open 系统调用过程
- linux open 系统调用过程
- Linux open系统调用流程
- Linux Kernel - open系统调用
- Linux open系统调用流程
- Linux中open、write、read、close系统调用
- linux系统调用流程浅析
- open系统调用在内核中的流程浅析
- 【转载】linux open 系统调用过程
- Linux系统调用之open(), close()
- Linux系统调用之open, close
- Linux系统中mkfifo创建管道后,调用open打开失败,不知道错在哪儿
- Linux 汇编语言开发指南
- ios6.0以前版本开发 异常信息:reason: ‘Could not instantiate class named NSLayoutConstraint’
- 进程间关系:进程、僵尸进程、孤儿进程、进程组、前台进程组、后台进程组、孤儿进程组、会话、控制终端
- 关于Classloader的总结!loadClass的分析和加载细节的分析
- Dell服务器Linux 网卡升级
- 浅析linux中open系统调用
- 梦中碎片
- 这几天ACROBAT给我闹毛病,老是出现这样的错误:Font Capture:AcrobatInfo.exe 应用程序错误
- 同一台电脑运行多apache服务
- No result defined for action *** and result success
- C语言模块化
- 浅析Input 子系统
- 如何更安全地使用 PDF 文档
- Java 理论与实践: 嗨,我的线程到哪里去了?