2021-10-24

5.系统调用

graph LR
A[应用程序]--调用-->B[库函数]
B--调用-->C[系统调用]
C--指挥-->D[操作系统]

POSIX是一套系统调用API规范,应用于LINUX,UNIX,macOS

5.3系统调用

系统调用会通过一个long类型返回值来表示成功或者错误,0为成功,负值是错误,错误码被保存在errno全局变量中。系统调用限定词为asmlinkage,为了兼容32位和64位,用户空间返回值为int,内核空间为long,另外系统调用和内核命名规则也不一样

5.3.1 系统调用号

每个系统调用都有一个系统调用号,此号不能轻易改变,删除一个号之后,用‘未实现系统调用函数’:sys_ni_syscall()填补空缺,该函数返回-ENOSYS,这些号被存在系统调用表里

系统调用处理程序

用户空间函数不可直接访问内核空间,但可以间接通知内核,使内核陷入内核态,使用软中断:system_call()实现内核陷入。
系统调用把
系统调用号
参数分别通过eax和其他五个寄存器传给内核

graph TB
A[用户空间函数]-->B[系统调用]
B--触发软中断-->C[system_call函数检查系统调用号是否小于NR_syscalls值]
C-->D[函数陷入内核空间检查参数权限合法性]
D-->E[系统调用号和参数通过寄存器传入内核]

参数验证

系统调用必须检查参数的合法性,不能传入访问不到的地址,比如:其他进程空间的,内核空间的,内存的只读只写。。。访问限制
权限的合法性通过suser()检查是否为超级用户,capable()检查对资源操作的权能

系统调用上下文

绑定系统调用

在entry.s文件里的调用表里添加一个表项,在**<asm/unisted>设置系统调用号,系统调用要被编译进内核映像kernel/**里

用户访问系统调用

用户可通过一组linux宏访问系统调用,它会设置好寄存器并调用陷入指令,
宏的形式为:

NR_open 5
_syscall3(long, open, const char*,filename,int,flags,int,mode) 第一二个参数对应着返回类型和系统调用名字