标签:
第五章 系统调用
一、与内核通信
系统调用在用户空间进程和硬件设备之间添加了一个中间层。作用:
在Linux中,系统调用是用户空间访问内核的唯一手段;除异常和陷入外,它们是内核唯一的合法入口。
二、API、POSIX和C库
一般情况下,应用程序通过在用户空间实现的应用编程接口(API)而不是直接通过系统调用来编程。
一个API定义了一组应用程序使用的编程接口。因为API实际上不需要和系统调用对应(API可以在各种不同的操作系统上实现),一个API可以实现成一个系统调用,也可以通过调用多个系统调用来实现,也可以完全不用。
POSIX、API、C库及系统调用关系如下:
在Unix世界中最流行的应用编程接口是给予POSIX标准的。
C库实现了大部分的POSIX标准API.
三、系统调用
要访问系统调用(在Linux中常称作syscall),通常通过C库中定义的函数调用来进行。
负的返回值表示错误,0值通常表示成功。系统调用在出现错误时C库会把错误码写入errno全局变量,通过调用perror()库函数,可以把该变量翻译成用户可以理解的错误字符串。
例如:获取进程ID号的系统调用getpid()
asmlinkage long sys_getpid(void) {
return current->tgid;
}
1、系统调用号
Linux中,每个系统调用号被赋予一个唯一的系统调用号,进程不会提及系统调用名称,而是用系统调用号来关联具体的系统调用。系统调用号一旦分配就不能再改变;如果一个系统调用被删除,它所占用的系统调用号也不允
许被回收利用。Linux有一个“未实现”系统调用sys_ni_syscall(),来补缺已经删除的调用号。
2、系统调用的性能
Linux系统调用比其他许多操作系统执行得要快:Linux很短的上下文切换时间,系统调用处理程序和每个系统调用本身也都非常简洁。
四、系统调用处理程序
用户空间的程序无法直接执行内核代码,通过软中断的机制通知内核需要执行系统调用。通过软中断引发一个异常,促使系统切换到内核态,执行异常处理程序代码;这个异常处理程序就是系统调用处理程序system_call()。在
x86系统上软中断是中断号128,通过int $0x80指令触发该中断system_call()。
在x86上,系统调用号是通过eax寄存器传递给内核的。
在x86-32系统上,ebx,ecx,edx,esi和edi依次存放前五个参数,若需要六个以上参数,用单独寄存器指向这些参数在用户空间地址的指针。通过eax存放返回值。
五、系统调用的实现
1、实现系统调用
2、参数验证
1)指向用户空间内存的指针,内核不能直接访问;
2)指针指向的内存在用户进程空间里,内核不能读其他进程空间;
3)内存不能绕过访问限制:可读内存标记为可读,可写标记为可写,可执行标记为可执行。
1)为了向用户空间写入数据内核提供了copy_to_user();
2)为了从用户空间读取数据内核提供了copy_from_user()。
3)都是把第二个参数指定位置数据传送到第一个参数指定位置,长度由第三个参数决定。如果执行失败,二者都返回未完成拷贝的数据的字节数,成功返回0。
4)copy_to_user()和copy_from_user()都可能引起阻塞造成进程休眠。
六、系统调用上下文
内核在执行系统调用的时候处于进程上下文,urrent指针指向引发系统调用的那个进程。
在进程上下文中,内核可以休眠,可以被抢占。所以系统调用必须是可重入的。
1、绑定一个系统调用的最后步骤
2、从用户空间访问系统调用:
3、采用系统调用作为实现方式
优点有:
缺点是:
替代方法:
七、总结
这一章讲了系统调用的知识,Linux尽量使系统调用简洁,事实上Linux已经是一个相对稳定并且功能已经较为完善的操作系统。本章的内容与视频上的知识相辅相成,有助于我们对系统调用的理解,我们了解了系统调用是什么,以及他们与API和库函数的关系。还有实现系统调用的过程,和参数验证,最后还总结了采用系统调用作为实现方式的利弊和代替方法。有助于我们理解和掌握。
标签:
原文地址:http://www.cnblogs.com/20135132yoggie/p/5311653.html