第五章:系统调用
5.1与内核通信
为用户空间提供了硬件接口;
系统调用保证了系统的稳定和安全;
公共接口。
5.2 API、POSIX和C库
关于Unix接口设计:提供机制而不是策略
5.3系统调用
asmlinkage long sys_getpid(void)
asmlinkage是限定词
long返回值类型
sys_getpid符合命名规则
5.3.1系统调用号
每个系统被赋予一个系统调用号
内核就是根据传入的系统调用号来知道是哪个系统调用的
5.3.2系统调用性能
执行速度快:
上下文切换时间短
系统调用处理程序和每个系统调用本身都很简洁
5.4系统调用处理程序
应用程序应该以某种方式通知系统,告诉内核自己需要一个系统调用
X86处理器增加了一条sysenter中断指令,更快更专业。
5.4.1指定恰当的系统调用
system_call()函数通过将给定的系统调用号与NR_syscalls作比较来检查其有效性。
大于等于返回-ENOSYS,否则执行相应系统调用:
call *sys_call_table(,%rax,8)
5.4.2参数传递
5.5系统调用的实现
实现一个新的LINUX调用的步骤
5.5.1实现系统调用
提供机制而不是策略
5.5.2参数验证
指针指向的内存区域必须属于用户空间;
指针指向的内存区域在进程的地址空间内;
决不能绕过内存访问限制。
内核无论何时都不能轻率地接受来自用户空间的指针。
5.6系统调用上下文
在进程上下文中
内核可以休眠
可以被抢占
5.6.1绑定一个系统调用的最后步骤
在系统调用表中加入表项;
系统调用号定义于<asm/unistd.h>中;
编译进内核映像,放入kernel/下的相关文件。
5.6.2从用户空间访问系统调用
对于每个宏来说,都有(2+2xn)个参数
n:0~6
第一个参数:对应系统调用返回值类型
第二个参数:系统调用的名称
5.6.3为什么不通过系统调用实现
建立一个系统调用的好处:
创建容易、使用方便
Linux系统调用的高性能
问题:
系统调用号需要在内核处于开发版本时官方分配
系统调用加入稳定内核后被固化,接口不允许做改动
需要将系统调用分别注册到每个需要支持的体系结构中去
脚本中不容易调用,不能从文件系统直接访问
主内核树之外难以维护和使用
替代方法:
某些接口可以用文件描述符表示
把增加的信息作为文件放在sysfs的合适位置
5.7小结:
通过讨论系统调用的优点和缺点和方案对本章进行总结。