韩玉琪 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

一、用户态、内核态和中断处理过程

1. 用户态和内核态

CPU指令执行级别
- 高级别:执行特权指令,访问任意的物理地址——内核态。
- 低级别:代码只能在级别允许的特定范围内活动——用户态。在日常操作下,执行系统调用的方式是通过库函数,库函数封装系统调用,为用户提供接口以便直接使用。
  • Intel x86 CPU有四种不同的执行级别0~3,Linux只用其中的0和3来表示内核态和用户态

  • 区分内核态和用户态:CPU每条指令的读取都是通过cs:eip,cs寄存器最低两位表明了当前代码的特权级。

    • 内核态下可访问所有地址空间
    • 0xc0000000(逻辑地址)以上的空间只能在内核态下访问
    • 0x00000000 ~ 0xbfffffff 内核态和用户态均可访问
  • 用户态转换为内核态的主要方式:中断

2. 中断处理

  • 用户态到内核态的切换:必须保存用户态的寄存器上下文,包括用户态栈顶地址、当时的状态字、cs:eip的值,以及内核态的栈顶地址、当时的状态字、中断处理程序入口。

    • 中断发生后的第一件事:保存现场(SAVE_ALL:保存需要用到的寄存器数据)。
    • 中断处理结束前的最后一件事:恢复现场(RESTORE_ALL:退出中断程序,恢复保存寄存器的数据)。
  • 完整过程:

二、系统调用

1. 意义

系统调用是操作系统为用户态进程与硬件设备进行交互提供的一组接口
  • 把用户从底层的硬件编程中解放出来
  • 极大的提高了系统的安全性
  • 使用户程序具有可移植性

2. API与系统调用

API:应用程序编程接口,是一个函数定义。
系统调用:通过软中断向内核发出一个明确的请求。
  • 一般每个系统调用对应一个封装例程,库再用这些封装例程定义出用户的API,方便用户使用。所以,API与系统调用不是一一对应的

      - API可以直接提供用户态服务(如:数学函数)
    - 一个单独的API可能调用几个系统调用
    - 不同的API可能调用了同一个系统调用
  • 返回值

      - 大部分封装例程返回一个整数,其值的含义依赖于相应的系统调用
    - -1表示内核不能满足进程请求
    - Libc中定义errno变量,包含特定出错码

3. 系统调用“三层皮”

- API
- 中断向量
- 中断服务程序
  • 当用户态进程调用一个系统调用时,CPU切换到内核态并开始执行一个内核函数。

  • Linux中是通过执行int $0x80来执行系统调用,这条汇编指令产生向量为128的编程异常 —— 即中断向量0x80与System_call绑定起来。

  • 系统调用号将函数xyz()和中断服务程序sys_xyz关联起来。

4. 参数传递

  • 内核实现了很多不同的系统调用,进程用系统调用号这个参数指明需要哪个系统调用。

  • system_call是linux中所有系统调用的入口点,每个系统调用至少有一个参数,使用eax寄存器传递系统调用号。

  • 寄存器传递参数的限制

      - 每个参数的长度不能超过寄存器的长度,即32位
    - 在系统调用号(eax)之外,参数的个数不能超过6个(ebx,ecx,edx,esi,edi,ebp)
    - 超过6个的情况下,使用某一个寄存器作为指针,进入内核态之后可以访问所有的地址空间,通过某一片区域传递参数。

三、使用库函数API和C代码中嵌入汇编代码触发同一个系统调用

1. 使用库函数API获取系统当前时间

2. 使用嵌入式汇编代码获取系统当前时间

  • 内嵌汇编在语法上要求先声明输出参数,然后声明输出参数值。

  • 系统调用的参数,按照顺序分别放在ebx、ecx、edx、esi、edi和ebp中。上述代码中time不需要参数,只需要一个输出值,所以ebx在这里是NULL。

  • eax传递系统调用号,这里time是13

  • 执行的效果与上面的是完全一样的:

我们使用int 0x80触发中断,然后中断处理程序保存现场,我们的进程陷入内核态。

四、实验

参考:系统调用列表

1. 选取了122号系统调用:uname

  • 获取当前内核名称和其它信息

2. 使用man查看有关uname的说明

  • man 2 uname

      - char sysname[_UTSNAME_SYSNAME_LENGTH];   //当前操作系统名
    - char nodename[_UTSNAME_NODENAME_LENGTH]; //网络上的名称
    - char release[_UTSNAME_RELEASE_LENGTH]; //当前发布级别
    - char version[_UTSNAME_VERSION_LENGTH]; //当前发布版本
    - char machine[_UTSNAME_MACHINE_LENGTH]; //当前硬件体系类型

3. 编写C语言代码并运行

4. 编写嵌入式汇编代码

5. 运行与比较

  • 在实验楼环境下运行

  • 可以运行出来,但是sysname是空的,没有搞明白为什么...

  • 同样的环境对比一下C语言代码

五、总结

1. 系统调用

  • 即便是最简单的程序,在进行输入输出等操作时也会需要调用操作系统所提供的服务,也就是系统调用。
  • Linux下的系统调用是通过中断(int 0x80)来实现的。

2. 传递参数

  • 在执行int 80指令时,寄存器 eax 中存放的是系统调用的功能号,而传给系统调用的参数则必须按顺序放到寄存器 ebx,ecx,edx,esi,edi 中,当系统调用完成之后,返回值可以在寄存器 eax 中获得。
  • Linux 采用的是 C 语言的调用模式,这就意味着所有参数必须以相反的顺序进栈,即最后一个参数先入栈,而第一个参数则最后入栈。

六、待解决问题

1. 为什么用嵌入式汇编代码运行的sysname是空?

  • 编写的代码:

  • 运行结果:

2. 问题解决

  • 反思一下其实是我一开始就没有认真看man中的信息,里面明确的写着:

      int uname(struct utsname *buf);
  • 返回值是int,传入指针之后系统调用直接将信息写入指针指向位置!

Linux内核分析第四周学习总结:扒开系统调用的三层皮(上)的更多相关文章

  1. LINUX内核分析第四周学习总结——扒开系统调用的“三层皮”

    LINUX内核分析第四周学习总结--扒开系统调用的"三层皮" 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>MOOC ...

  2. 《Linux内核分析》 第四节 扒开系统调用的三层皮(上)

    <Linux内核分析> 第四节 扒开系统调用的三层皮(上) 张嘉琪 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com ...

  3. 《Linux内核分析》 第五节 扒开系统调用的三层皮(下)

    <Linux内核分析> 第五节 扒开系统调用的三层皮(下) 20135307 一.给MenusOS增加time和time-asm命令 给MenuOS增加time和time-asm命令需要 ...

  4. 《Linux内核分析》第五周 扒开系统调用的三层皮(下)

    [刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK FIVE( ...

  5. #Linux第四周学习总结——扒开系统调用的三层皮(上)

    Linux第四周学习总结--扒开系统调用的三层皮(上) 一.用户态.内核态和中断 系统调用通过库函数. 1.用户态和内核态 区分(不同的指令执行级别): 用户态:在相应的低执行状态下,代码的掌控范围受 ...

  6. LINUX内核分析第四周学习总结——扒开应用系统的三层皮(上)【转】

    转自:http://www.cnblogs.com/lalacindy/p/5276874.html 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://moo ...

  7. 20135337朱荟潼 Linux第四周学习总结——扒开系统调用的三层皮(上)

    朱荟潼 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课http://mooc.study.163.com/course/USTC 1000029000 知识点梳理 一.用 ...

  8. LINUX内核分析第五周学习总结——扒开系统调用的“三层皮”(下)

    LINUX内核分析第五周学习总结--扒开系统调用的"三层皮"(下) 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>M ...

  9. linux内核分析第四周学习笔记

    linux内核分析第四周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...

  10. Linux内核分析第四周学习总结——系统调用的工作机制

    Linux内核分析第四周学习总结--系统调用的工作机制 内核态 执行级别高,可以执行特权指令,访问任意物理地址,在intel X86 CPU的权限分级为0级. 用户态 执行级别低,只能访问0x0000 ...

随机推荐

  1. JS eval() 特殊用法

    最近项目有 有个模块 有若干功能菜单,这些菜单查询部分都是一样的,所以就像提取一个通用的查询页面然后使用$('#ele').load('../**.aspx #searchID', {}, funct ...

  2. day17算法

    http://www.360doc.com/content/14/0804/11/1073512_399302715.shtml

  3. selenium多个窗口切换

    浏览器里面支持多窗口打开,例如这样: html里面写了: target="_blank" 造成新打开一个窗口,但是selenium不会自动跳转到新的串口,需要自己切换: # 你打开 ...

  4. Morphia 学习一 注解

    http://blog.csdn.net/liumm0000/article/details/7535858 生命周期方法注解(delete没有生命周期事件)@PrePersist save之前被调用 ...

  5. 【转】Linux CentOS内核编译:下载CentOS源码、编译2.6.32-220的错误(apic.c:819 error 'numi_watchdog' undeclared)

    一.下载CentOS源码 1.1 查看CentOS版本 cat /etc/issue 1.2 查看Linux内核版本 uname -r 1.3 下载 文件名:kernel-2.6.32-220.el6 ...

  6. [HTML5]块和内联元素的嵌套

    块元素可以包含块或内联元素,但是内联元素只能包含其他内联元素. <!-- 无效代码! :-( --> <strong> <p>你不应该把p元素放在 "st ...

  7. UVA 753 UNIX 插头(EK网络流+Floyd传递闭包)

    UNIX 插头 紫书P374 [题目链接]UNIX 插头 [题目类型]EK网络流+Floyd传递闭包 &题解: 看了书之后有那么一点懂了,但当看了刘汝佳代码后就完全明白了,感觉他代码写的好牛逼 ...

  8. centos7编译安装pure-ftpd-1.0.42

    一.下载 wget https://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.42.tar.gz 二.安装 tar xvf ...

  9. pl/sql和sql的区别

    源地址:https://zhidao.baidu.com/question/187511430.html 1 sql(数据定义语言) 和PL/Sql的区别:答:SQL是结构化查询语言,比较接近自然语言 ...

  10. mybatis配置优化

    1.加入日志log4j 1)加入jar包:log4j-1.2.17.jar 2)加入log4j配置文件: 可以使properties或者xml形式 log4j.rootLogger = DEBUG,C ...