第五章  系统调用

5.1与内核通信

1. 系统调用

让应用程序受限的访问硬件设备
提供创建新进程并与已有进程通信的机制
提供申请操作系统其他资源能力
是用户空间进程和硬件设备之间的中间层

2. 系统调用的功能

1)硬件的抽象接口:用户程序通过系统调用来使用硬件,而不用关心具体的硬件设备,简化了用户程序的开发

2)保证系统的稳定与安全:基于某些规则的访问控制

3)增强系统的稳定性

  • 在Linux中,系统调用是用户空间访问内核的唯一手段
  • 除异常和陷入外,他们是内核唯一的合法入口

5.2 API、POSIX和C库

1.API可以在各种不同的操作系统实现,给应用程序提供完全相同的接口,而它们本身在这些系统上的实现却可能迥异。

2.在Unix世界中,最流行的应用编程接口是基于POSIX标准的。

3. C库包括:标准C库函数、系统调用接口

4. 注意:

程序员<--->API
内核<--->系统调用

5.关系图:

5.3系统调用

1. 介绍:在linux中常称作syscall,通常通过C库中定义的函数调用来进行。

  • 注意:返回值是long型变量,如果出错,C库会将错误代码写入errno全局变量。
  • 系统调用再出现错误的时候C库会把错误码写入errno全局变量。通过调用perror()库函数,可以把该变量翻译成用户可以理解的错误字符串。
  • SYSCALL_DEFINE0只是一个宏,它定义一个无参数的系统调用。

2. 定义系统调用:

asmlinkage long sys_getpid(void)
  • 限定词:asmlinkage
  • 函数返回值类型:long
  • 符合命名规则的命名:sys_getpid

3. 系统调用在用户空间和内核空间有不同的返回值类型,在用户空间为int在内核空间为long。

4. 系统调用号一旦分配就不能再有任何变更。

  • 如果一个系统调用被删除,它所占用的系统调用号也不允许被回收利用
  • Linux有一个“未实现”系统调用sysnisyscall(),它除了返回―ENOSYS外不做任何其他工作,这个错误号就是专门针对无效的系统调用而设的

5.4 系统调用处理程序

1. 内核记录了系统调用表中的所有已注册过的系统调用的列表,存储在syscalltable中。在×86-64中,它定义于arch/i386/kernel/syscall_64.c文件中。

2.注意:

x86系统,ebx,ecx,edx,esi,edi按顺序存放前五个参数。
需要6个及以上参数,应用一个单独的寄存器存放指向这些参数在用户空间地址的指针。
返回值存放在eax。

3. Linux系统执行快的原因:

  • 很短的上下文切换时间
  • 系统调用处理程序和每个系统调用本身也十分简洁

5.5 系统调用的实现

1.参数验证

  • 参数合法有效并正确:不应让内核访问无权访问的资源
  • 最重要的检查:用户提供的指针是否有效。内核必须保证指针:

    指向的内存区域属于用户空间;
    指向的内存区在进程的地址空间里;
    指向的内存区在内存的访问权限范围中。
  • 两个方法检查在两空间之间数据的来回拷贝:
    copy_to_user():向用户空间写入数据
    copy_from_user():从用户空间读取数据
  • 针对是否有合法权限的检查
    capable():是否有权对指定的资源进行操作
    返回0:无权操作

2.关系图:

5.6 系统调用上下文

1. 进程上下文:内核在执行系统调用的时候处于进程上下文

current指针指向当前任务。
在进程上下文中,内核可以休眠、被抢占。
当系统调用返回时,控制权仍然在system_call()中,负责切换到用户空间,并让用户进程继续执行下去

2. 绑定一个系统调用的最后步骤:编写完系统调用之后,将其注册成一个正式的系统调用

在系统调用表中加入表项;
系统调用号定义于<asm/unistd.h>中;
编译进内核映像,放入kernel/下的相关文件。

3. 从用户空间访问系统调用

  1. _syscalln():Linux提供的一组宏,用于直接对系统调用进行访问。会设置好寄存器并调用陷入指令。
  2. n的范围:0~6,代表传递给系统调用的参数个数。
  3. 对每个宏来说,都有2+2*n个参数。
第一个参数:对应系统调用返回值类型
第二个参数:系统调用的名称
按系统调用参数顺序排列的每个参数的类型和名称 
eg.
long open(const char *filename, int flags, int mode)
#define NR_open 5
_syscall3(long, open, const char*, filename, int, flags, int, mode)

4. 为什么不通过系统调用的方式实现?

(1)建立一个系统调用的好处

创建容易、使用方便
Linux系统调用的高性能

(2)问题是:

系统调用号需要在内核处于开发版本时官方分配
系统调用加入稳定内核后被固化,接口不允许做改动
需要将系统调用分别注册到每个需要支持的体系结构中去
脚本中不容易调用,不能从文件系统直接访问
主内核树之外难以维护和使用

(3)替代方法

某些接口可以用文件描述符表示
把增加的信息作为文件放在sysfs的合适位置

=======================================================

总结

我觉得在这一章中,最应该重点理解的还是系统调用的内涵,以及它和API的区别。也提及补充了系统调用的优势之处。这也让我们从底层能够比较系统地去理解内核运行机制,它是如何提供基本功能的,其中包含的那些层层包装递进的过程。

《Linux内核设计与实现》第五章读书笔记的更多相关文章

  1. Linux内核设计与实现第五周读书笔记

    第十八章 调试 18.1准备开始 需要的只是: 一个确定的bug.大部分bug通常都不是行为可靠而且定义明确的. 一个藏匿bug的内核版本. 相关的内核代码的知识和运气. 18.2内核中的bug 内核 ...

  2. 《Linux内核设计与实现》第四周读书笔记——第五章

    <Linux内核设计与实现>第四周读书笔记--第五章 20135301张忻 估算学习时间:共1.5小时 读书:1.0 代码:0 作业:0 博客:0.5 实际学习时间:共2.0小时 读书:1 ...

  3. 《Linux内核设计与实现》Chapter 3 读书笔记

    <Linux内核设计与实现>Chapter 3 读书笔记 进程管理是所有操作系统的心脏所在. 一.进程 1.进程就是处于执行期的程序以及它所包含的资源的总称. 2.线程是在进程中活动的对象 ...

  4. 《Linux内核设计与实现》Chapter 1 读书笔记

    <Linux内核设计与实现>Chapter 1 读书笔记 一.Unix的特点 Unix从Multics中产生,是一个强大.健壮和稳定的操作系统. 特点 1.很简洁 2.在Unix系统中,所 ...

  5. 《Linux内核设计与实现》Chapter 5 读书笔记

    <Linux内核设计与实现>Chapter 5 读书笔记 在现代操作系统中,内核提供了用户进程与内核进行交互的一组接口,这些接口的作用是: 使应用程序受限地访问硬件设备 提供创建新进程与已 ...

  6. 《Linux内核设计与实现》Chapter 18 读书笔记

    <Linux内核设计与实现>Chapter 18 读书笔记 一.准备开始 一个bug 一个藏匿bug的内核版本 知道这个bug最早出现在哪个内核版本中. 相关内核代码的知识和运气 想要成功 ...

  7. LINUX内核设计与实现第三周读书笔记

    LINUX内核设计与实现第三周读书笔记 第一章 LINUX内核简介 1.1 Unix的历史 1969年的夏天,贝尔实验室的程序员们在一台PDR-7型机上实现了Unix这个全新的操作系统. 1973年, ...

  8. 《Linux内核设计与实现》Chapter 2 读书笔记

    <Linux内核设计与实现>Chapter 2 读书笔记 一.获取内核源码 1.使用Git 我们曾经在以前的学习中使用过Git方法 $ git clone git://git.kernel ...

  9. Linux内核设计与实现 第五章

    1. 什么是系统调用 系统调用就是用户程序和硬件设备之间的桥梁. 用户程序在需要的时候,通过系统调用来使用硬件设备. 系统调用的存在意义: 1)用户程序通过系统调用来使用硬件,而不用关心具体的硬件设备 ...

  10. Linux内核设计与实现第十周读书笔记

    第十七章 设备与模块 关于设备驱动与设备管理,我们讨论四种内核成分. 设备类型 模块 内核对象 sysfs 17.1设备类型 在Linux以及所有Unix系统中,设备被分为以下三种类型: 块设备,块设 ...

随机推荐

  1. BZOJ2079:[POI2010]Guilds(乱搞)

    Description Zy皇帝面临一个严峻的问题,两个互相抵触的贸易团体,YYD工会和FSR工会,他们在同一时间请求在王国各个城市开办自己的办事处.这里有n个城市,其中有一些以双向马路相连,这两个工 ...

  2. BZOJ3233:[AHOI2013]找硬币(DP)

    Description 小蛇是金融部部长.最近她决定制造一系列新的货币.假设她要制造的货币的面值为x1,x2,x3… 那么x1必须为1,xb必须为xa的正整数倍(b>a).例如 1,5,125, ...

  3. layui小封装方法

    //打开加载动画function LayerLoad() { layui.use('layer', function () { var layer = layui.layer; layer.load( ...

  4. Python2.7-bz2

    bz2模块,提供 bz2 压缩的接口,一般使用 BZ2File 类来完成操作,操作的文件是后缀为“.bz2”的文件 1.模块方法 bz2.compress(data[, compresslevel]) ...

  5. Python2.7-bisect

    bisect 模块,对已经排好序的序列进行筛选,添加新元素,效率高,不用在插入新元素后重新排序,可以快速找到小于指定值的位置 个人想法:与 heapq 的堆可以较好的结合使用 模块方法:bisect_ ...

  6. spring amqp初步了解

    Rabbitmq简介 生产者会把消息发送给RabbitMQ的交换中心(Exchange),Exchange的一侧是生产者,另一侧则是一个或多个队列,由Exchange决定一条消息的生命周期--发送给某 ...

  7. Kafka设计解析(二十一)Kafka水位(high watermark)与leader epoch的讨论

    转载自 huxihx,原文链接 Kafka水位(high watermark)与leader epoch的讨论 本文主要讨论0.11版本之前Kafka的副本备份机制的设计问题以及0.11是如何解决的. ...

  8. JAVA之多线程概念及其几种实现方法优劣分析

    1. 多线程 程序:指令集,静态的概念 进程:操作系统调动程序,是程序的一次动态执行过程,动态的概念 线程:在进程内的多条执行路径 Ps:单核的话进程都是虚拟模拟出来的,多核处理器才可以执行真正的多线 ...

  9. Theano3.7-练习之堆叠消噪自动编码器

    来自:http://deeplearning.net/tutorial/SdA.html#sda Stacked Denoising Autoencoders (SdA) note:这部分需要读者读过 ...

  10. 第36章 SDIO—SD卡读写测试

    第36章     SDIO—SD卡读写测试 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/f ...