系统调用
系统调用框架
系统调用的参数传递,由用户态进入了内核态,所以既不能使用用户态的堆栈也不能直接使用内核态堆栈;所以系统调用的参数被写入CPU的寄存器;在进入内核态调用系统调用服务例程之前,通过使用SAVE_ALL宏把这些寄存器的值保存在内核态堆栈中:eax保存徐通调用号和返回值;ebx,ecx,edx,esi,edi保存参数
这样系统调用处理程序一旦运行,就可以从eax中得到系统调用号:比如open()封装例程
那么在执行int $0x80之前就把eax寄存器的值置为5(即__NR_open);然后再去系统调用表中寻找相应服务例程(.long SYMBOL_NAME(sys_open)
open系统调用栈
上面看到了一个系统调用是怎么去到内核态的,下面看下具体的open系统调用的调用栈
read系统调用
不管不同设备驱动的底层实现如何有差异,操作系统的接口肯定会屏蔽这种差异,统一的虚拟文件系统(vfs)的接口去实现
不同内核版本实现不一样,5.17的内核版本如下字符设备一般是file_operations的read;块设备一般是file_operations的read_iter,具体实现看源码,各个内核版本大同小异