第五章 系统调用

一、与内核通信

系统调用在用户控件进程和硬件设备之间添加了一个中间层,作用如下“

  • 为用户空间提供了一种硬件的抽象接口
  • 系统调用保证了系统的稳定和安全
  • 每个进程都运行在虚拟系统中,而在用户控件和系统的其余部分提供这样一层公共接口

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

※系统调用与API的不同在于运行级别的切换。

二、API、POSIX和C库

POSIX、API、C库和系统调用之间的关系如下图:



POSIX-Unix世界中最流行的应用编程接口是给予POSIX标准的。

Linux的系统调用作为C库的一部分提供。

C库实现了Unix系统的主要API,包括标准C库函数和系统调用接口,即POSIXdM大部分API。

Unix的接口设计——“提供机制而不是策略”

三、系统调用

系统调用- syscall

通常通过C库中定义的函数调用来进行系统调用。

几种常见机制:

- 通过返回一个long型的返回值来表示成功或者错误
- 用一个负的返回值来表明错误
- 返回0代表成功
- 系统调用出现错误的时候会把错误码写入errno全局变量
- 通过perror()库函数可以把该变量翻译成用户可以理解的错误字符串

定义系统调用:

例:asmlinkage long sys_getpid(void)

1. asmlingkage,这是一个编译指令,通知编译器仅从栈中提取该函数的参数。所有的系统调用都需要这个限定词。
2. 返回值long。
为了保证32位和64位系统的兼容,系统调用在用户空间返回值int,内核空间long
3. 命名规则:sys_xxx

1.系统调用号

每个系统调用号独一无二,一旦分配就不能再有任何变更。

执行系统调用时,通过系统调用号指明,进程不会提及系统调用的名称。

未实现系统调用——sys_ni_syscall(),返回-ENOSYS,针对无用的系统调用。

2.系统调用的性能——执行速度快

原因?

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

四、系统调用处理程序

因为用户控件不能直接执行内核代码,需要切换内核态,它需要用某种方式告知内核,自己需要执行一个系统调用,请求切换到内核态,这个通知内核的机制是软中断

——通过引发一个异常来促使系统切换到内核态中去执行异常处理程序,即系统调用处理程序system_call()。

中断号128,指令如下:

int 128
或者
int 0x80 退出是iret

※新指令sysenter,比int中断指令更快更专业。

1.指定恰当的系统调用

2.参数调用

这两节讲述的内容在视频中亦有体现,不在此重复。

新知识点:

system_call()函数通过将给定的系统调用号与NR_syscalls作比较来检查其有效性。大于等于返回-ENOSYS,否则执行相应系统调用:

call *sys_call_table(,%rax,8)

过程:

int 0x80 → 中断向量表中找到对应中断向量 →系统调用表,

JMP(EAX*4 + system_xxx)

乘以4是因为系统调用表中的表象是以64位存放的。

五、系统调用的实现

1.实现系统调用

  • 决定它的用途

    不提倡采用多用途的系统调用
  • 确定参数、返回值、错误码

    力求简洁
  • 越通用越好,不做错误假设
  • 时刻注意可移植性和健壮性

2.参数验证

必须检查每个参数,保证他们不但合法有效,而且正确。

最重要——检查用户提供的指针:

- 指针指向的内存区域必须属于用户空间
- 指针指向的内存区域在进程的地址空间内
- 决不能绕过内存访问限制

内核无论何时都不能轻率地接受来自用户空间的指针。

※1.检查读写

(1)向用户空间写入数据——copy_to_user()

参数:

进程空间中的目的内存地址
内核空间内的源地址
需要拷贝的数据长度

(2)从用户控件读取数据——copy_from_user()

把第二个参数指定的位置上的数据拷贝到第一个参数指定的位置上

第三个参数——拷贝数据长度。

以上两个函数成功返回0,失败返回没能完成拷贝的数据的字节数。

这两个函数都有可能引起阻塞——当包含用户数据的页被换出到硬盘上而不是物理内存上的时候。

※2.检查是否有合法权限

老版本:suser()

新版本:权能机制,capable(),返回非0有权操作,返回0则无权操作。

六、系统调用上下文

内核在执行系统调用时处于进程上下文。

在进程上下文中,内核可以:

  • 休眠

    说明系统调用可以使用内核提供的绝大部分功能
  • 可以被抢占

    要求保证该系统调用是可重入的

1.绑定一个系统调用的最后步骤

1,在系统调用表的最后加入一个表项。
2,对于所支持的各种体系结构,系统调用号都必须定义于<asm/unistd.h>中
3,系统调用必须被编译进内核映像,不能被编译成模块。——放进kernel/下的一个相关文件中即可,例如sys.c。

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

Linux本身提供了一组宏,用于直接对系统调用进行访问。

_syscalln()     //n的范围从0到6,代表需要传递给系统调用的参数个数。

例如:

long open(const char *filename, int flags, int mode)
=
#define NR_open 5
_syscall3(long, open,const char*, filename, int, flags, int, mode)
应用程序可以直接用open()了。

对于每个宏来说,都有(2+2xn)个参数:

1.系统调用的返回值类型
2.系统调用的名称
以后按照系统调用参数的顺序排列每个参数的类型和名称。

_NR_open在<asm/unistd.h>中定义。

这个宏会被扩展成为内嵌汇编的C函数。

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

好处:

- 系统调用创建容易并且使用方便
- linux系统调用的高性能

问题:

- 占用系统调用号
- 固化,不允许改动接口
- 需要分别注册到每个需要支持的体系结构中
- 脚本中不易调用,文件系统中也不能直接访问
- 在主内核树外难以维护使用
- ……

替代:

- 某些接口,例如信号量,用文件描述符表示
- 把增加的信息作为一个文件放在sysfs的合适位置。

总而言之——

Linux尽量避免每出现一种新的抽象就简单地加入一个新的系统调用。

七、 学习心得

这一章前半部分在视频中学过,因此学习起来毕竟轻松,我也省略了一些重复的知识以精简这篇学习笔记;而后半部分目测是下周的内容,光从书本上学习没有视频直观,老师上课也补充了一部分,我会在下周的课程中继续认真学习。

20135202闫佳歆--week4 课本第5章学习笔记的更多相关文章

  1. 20135202闫佳歆--week6 课本第三章学习笔记

    第三章 进程管理 一.进程 1.进程 进程就是处于执行期的程序. 进程就是正在执行的程序代码的实时结果. 进程是处于执行期的程序以及相关的资源的总称. 进程包括代码段和其他资源. 2.线程 执行线程, ...

  2. 20135202闫佳歆--week4 系统调用(上)--学习笔记

    此为个人笔记存档 week 4 系统调用(上) 一.用户态.内核态和中断处理过程 用户通过库函数与系统调用联系起来. 1.内核态 在高执行级别下,代码可以执行特权指令,访问任意的物理地址. 2.用户态 ...

  3. 20135202闫佳歆--week5 系统调用(下)--学习笔记

    此为个人笔记存档 week 5 系统调用(下) 一.给MenuOS增加time和time-asm命令 这里老师示范的时候是已经做好的了: rm menu -rf 强制删除 git clone http ...

  4. 20135202闫佳歆--week4 两种方式使用同一个系统调用--实验及总结

    实验四 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 在这里我选择的是第20号系统调用,getpid. 1.使用库函数API: 代码如下: /* getpid.c */ #incl ...

  5. 20135202闫佳歆--week3 课本1-2章学习笔记

    第一章 Linux内核简介 一.Unix Unix是一个强大.健壮和稳定的操作系统. 简洁 绝大部分东西都被当做文件对待.这种抽象使对数据和对设备的操作都是通过一套相同的系统调用借口来进行的:open ...

  6. 20135202闫佳歆--week5 课本18章学习笔记

    第十八章 调试 内核级开发的调试工作远比用户级开发艰难的多. 一.准备开始 准备工作需要的是: 一个bug 一个藏匿bug的内核版本 相关内核代码的知识和运气 在这一章里,调试的主要思想是让bug重现 ...

  7. 20135202闫佳歆--week 7 Linux内核如何装载和启动一个可执行程序--实验及总结

    week 7 实验:Linux内核如何装载和启动一个可执行程序 1.环境搭建: rm menu -rf git clone https://github.com/megnning/menu.git c ...

  8. 《Linux内核设计与实现》课本第五章学习笔记——20135203齐岳

    <Linux内核设计与实现>课本第五章学习笔记 By20135203齐岳 与内核通信 用户空间进程和硬件设备之间通过系统调用来交互,其主要作用有三个. 为用户空间提供了硬件的抽象接口. 保 ...

  9. 20135202闫佳歆--week 9 期中总结

    期中总结 前半学期的主要学习内容是学习mooc课程<Linux内核分析>以及课本<Linux内核设计与实现>. 所涉及知识点总结如下: 1. Linux内核启动的过程--以Me ...

随机推荐

  1. 第二次项目冲刺(Beta版本)2017/12/10

    一.任务分布 二.燃尽图 三.站立式会议 1.照片(再给我两分钟) 2.任务安排 四.总结 冲刺的最后一天了,时间安排的不够好,还有部分功能没有完成,大家都尽力了,我们后续会抓紧时间完成项目.

  2. 6.基本数据结构-双端队列(Deque)

    一.双端队列(Deque) - 概念:deque(也称为双端队列)是与队列类似的项的有序集合.它有两个端部,首部和尾部,并且项在集合中保持不变. - 特性:deque 特殊之处在于添加和删除项是非限制 ...

  3. 如何将XML文件导入Excel中

    如下图所示为一个规范的XML文件,在Excel中可以将规范的XML文件导入到Excel成为规范的表格.具体有如下几种方法:   工具/原料   Excel 方法/步骤     单击“数据”选项卡下的“ ...

  4. Algorithms: 二叉平衡树(AVL)

    二叉平衡树(AVL):   这个数据结构我在三月份学数据结构结构的时候遇到过.但当时没调通.也就没写下来.前几天要用的时候给调好了!详细AVL是什么,我就不介绍了,维基百科都有.  后面两月又要忙了. ...

  5. 【华为机试】找最高分(通过此题熟悉牛客网Node输入输出)

    来源:牛客网 老师想知道从某某同学当中,分数最高的是多少,现在请你编程模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. 输入描述: 输入包括多组测试数据.每组输入第一行是两个正整数N和M(0 ...

  6. oracle 创建create user 及授权grant 查看登陆的用户

    show user; select sys_context('userenv','session_user') from dual; select user from dual; 查看所有登录的用户必 ...

  7. Sql注入测试--Sqlmap

    慕课网sqlmap学习笔记: 一.SQL注入 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令. 例如 (1)在url上 ...

  8. 利用jenkins打造通过自定义参数更新svn 指定文件任务

    jenkin可以执行很多构建任务,有时候我们需要在执行构成中同构shell对服务器进行操作而且还需要进行参数的传入 比如:我要利用svn进行本地代码的更新,单又不是所有代码的更新,只更新指定的1个或这 ...

  9. PAT B1017 A除以B (20 分)

    本题要求计算 /,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数.你需要输出商数 Q 和余数 R,使得 A=B×Q+R成立. 输入格式: 输入在一行中依次给出 A 和 B,中间以 1 ...

  10. RTSP server 在mips 上莫名其妙退出(PC上则无此问题)

    http://blog.csdn.net/lubing20044793/article/details/38523701 早在这篇blog以前写过,在虚拟机下调试sn9c291时,USB 数据传输出了 ...