标签:
20135307 张嘉琪
系统调用在用户空间进程和硬件设备之间添加了一个中间层,该层主要作用有三个:
在Linux中,系统调用是用户空间访问。内核的唯一手段;除异常和陷入外,它们是内核唯一的合法入口。
本章重点强调Linux系统调用的规则和实现方法。
在Linux中,每个系统调用被赋予一个系统调用号。这样,通过这个独一无二的号就可以关联系统调用。当用户空间的进程执行一个系统调用的时候,这个系统调用号就用来指明到底是要执行哪个系统调用。
系统调用号一旦分配就不能再有任何变更,否则编译好的应用程序就会崩溃。此外,如果一个系统调用被删除,它所占用的系统调用号也不允许被回收利用,否则,以前编译过的代码会调用这个系统调用,但事实上却调用的是另一个系统调用。
内核记录了系统调用表中的所有已注册过的系统调用的列表,存储在syscalltable中。
每一种体系结构中,都明确定义了这个表,在×86-64中,它定义于arch/i386/kernel/syscall_64.c文件中。这个表为每一个有效的系统调用指定了唯一的系统调用号。
Linux系统执行快的原因:
必须把系统调用号一并传给内核。
在x86上,系统调用号是通过eax寄存器传递给内核的。
除了系统调用号外,大部分系统调用都还需要一些外部的参数输入。
最简单的办法是像传递系统调用号一样,把这些参数也放在寄存器里。
系统调用必须仔细检查它们所有的参数是否合法有效。系统调用在内核空间执行,如果任由用户将不合法的输入传递给内核,那么系统的安全和稳定将面临极大的考验;
最重要的一种检查就是检查用户提供的指针是否有效。试
在接收一个用户空间的指针之前,内核必须保证:
内核在执行系统调用的时候处于进程上下文。在进程上下文中,内核可以休眠并且可以被抢占。
当系统调用返回的时候,控制权仍在system_call()中,它最终会负责切换到用户空间,并让用户进程继续执行下去。
当编写完一个系统调用后,把它注册成一个正式的系统调用是件琐碎的工作:
建立一个新的系统调用的好处
系统调用创建容易且使用方便。
Linux系统调用的高性能显而易见。
建立一个新的系统调用的问题
你需要―个系统调用号,而这需要一个内核在处于开发版本的时候由官方分配给你。
系统调用被加入稳定内核后就被固化了,为了避免应用程序的崩溃,它的接口不允许做改动
需要将系统调用分别注册到每个需要支持的体系结构中去。
在脚本中不容易调用系统调用,也不能从文件系统直接访问系统调用。
由于你需要系统调用号,因此在主内核树之外是很难维护和使用系统调用的。
如果仅仅进行简单的信息交换系统调用就大材小用了。
替代方法
实现一个设备节点,并对此实现read()和write()。使用特定的信息进行检索。
像信号量这样的某些接口,可以用文件描述符来表示,因此也就可以按上述方式对其进行操作
把增加的信息作为一个文件放在sysfs的合适位置。
在本章,我们描述了系统调用到底是什么,它们与库函数和应用程序接口有怎样的关系。
然后,我们考察了Linux内核如何实现系统调用,以及以及执行系统调用的连锁反应:陷入内核,传递系统调用号和参数,执行正确的系统调用函数,并把返回值带回用户空间。 然后,我们讨论了如何增加系统调用,并提供了从用户空间调用系统调用的简单例子。整个过程相当容易!增加一个新的系统调用没有什么难的,这一过程也就是系统调用的实现过程。书的其余部分讨论了编写规范的、最优化的、安全的系统调用所遵循的概念和内核接口规范。
最后,通过讨论实现系统调用的优缺点以及列举其替代方案的形式对全章内容进行了总结。
标签:
原文地址:http://www.cnblogs.com/Juliet5307/p/5325449.html