i. 系统调用产生的原因
为了用户空间和内核空间运行的进程进行交互,内核提供了一组接口。通过该接口,应用程序可以访问硬件设备和其他操作系统资源。这组接口就是系统调用。
系统调用在用户空间进程和硬件设备之间添加了一种中间层。主要作用有三个:
1. 为用户空间提供了硬件的抽象接口。把用户从学习硬件设备的低级编程特性中解放出来。
2. 系统调用保证了系统的稳定和安全。内核在试图满足某个请求之前在接口级就可以检查这种请求的正确性。
3. 这些接口使得程序更具有可移植性,只要内核所提供的一组接口相同,那么在任一内核上都能正确的编译和执行程序。
在linux中,系统调用是用户空间访问内核的唯一手段,除异常和陷入外,它们是内核唯一的合法入口。其他的像设备文件和/proc之类的方式,最终还是通过系统调用进行访问的。
ii. 应用程序,C库内核之间的关系
iii. 系统调用的简单实现以及使用
a) 内核空间
1. 在entry.s表的末尾添加.long sys_foo
2. 在<asm/unistd.h>添加系统调用号: #define _NR_foo 283
3. 在kernel/sched.c中实现系统调用:
b) 用户空间
iv. 系统调用说明
1. 系统调用号
Linux中,每个系统调用赋予一个系统调用号。用户空间的进程执行一个系统调用的时候,这个系统调用号用来指明要执行哪个系统调用。内核记录了系统调用表中的所有已注册过的系统调用列表,存储在sys_call_table中。
2. 系统调用程序
用户空间的程序无法直接调用内核空间中的函数,因为内核驻留在受保护的地址空间上。应用程序以某种方式通知系统,告诉内核自己需要执行一个系统调用,希望内核切换到内核态,这样内核可以代表应用程序执行系统调用。
通知内核的机制是靠软中断实现的:通过引发一个异常来促使系统切换到内核态去执行异常处理程序-系统调用处理程序。X86系统上的软中断由int 0x80指令产生。这条指令触发一个异常导致系统切换到内核态并执行128号处理程序,而该程序通过系统调用号执行相应的系统调用处理程序。
3. C库问题
通常,系统调用靠C库支持。用户程序通过包含标准头文件和C库链接,就能使用系统调用。但自己写出的系统调用,glibc库可能并不支持。Linux提供了一组宏,用于直接对系统调用访问。这些宏是_syscalln(),n的范围从0到6.代表需要传递给系统调用的参数的个数。