LINUX内核分析第四周——扒开系统调用的三层皮

李雪琦 + 原创作品转载请注明出处 + 《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表示失败,不能满足请求
  • errno 特定出错码

3.所谓“扒开系统调用的三层皮”

  • API(xyz)
  • 中断向量(system_call)
  • 中断服务程序(sys_xyz)

1.系统调用的服务例程中,中断向量0x80与system_call绑定起来。(Linux中可以通过执行int $128来执行系统调用。)

2.system_call是linux中所有系统调用的入口点,每个系统调用至少有一个参数,即系统调用号。

3.系统调用号将xyz与sys_xyz关联起来。调用号在eax中。
系统调用的参数传递:

  • 函数调用——压栈
  • 用户态到内核态——寄存器传递。

每个参数长度不能超过32位,个数不能超过6个。

超过的话,使某个寄存器中存储指针,指向内存,内存中存储参数。

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

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

使用time(),代码如下:

#include<stdio.h>
#include<time.h>
int  main()
{
time_t tt;
struct tm *t;//构造一个结构体,方便读取
tt = time(NULL);//time系统调用
t = localtime(&tt);
printf("time:%d:%d:%d:%d:%d:%d\n", t->tm_year+1900, t->tm_mon, t->tm_mday,  t->tm_hour, t->tm_min, t->tm_sec);
return 0;
} 

2.使用C代码中嵌入汇编代码触发系统调用获取系统当前时间

代码如下:

#include<stdio.h>
#include<time.h>
int  main()
{
time_t tt;
struct tm *t;
asm volatile(
"mov $0,%%ebx\n\t"  # 把ebx清零,相当于传参数
"mov $0xd,%%eax\n\t"# 把0xd放入eax中,即系统调用号13,指time
"int $0x80\n\t"
"mov %%eax,%0\n\t"  # 返回值是在eax中,%0指tt,把返回值放到tt中去。
: "=m" (tt)
);
t = localtime(&tt);
printf("time:%d:%d:%d:%d:%d:%d\n", t->tm_year+1900, t->tm_mon, t->tm_mday,  t->tm_hour, t->tm_min, t->tm_sec);
return 0;
} 

四、使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

在这里我选择的是第7号系统调用,waitpid。

1.使用库函数API:

2.嵌入汇编:

3.运行结果:

五、总结

  • 即便是最简单的程序,在进行输入输出等操作时也会需要调用操作系统所提供的服务,也就是系统调用。
  • Linux下的系统调用是通过中断(int 0x80)来实现的。
  • 在执行int 80指令时,寄存器 eax 中存放的是系统调用的功能号,而传给系统调用的参数则必须按顺序放到寄存器 ebx,ecx,edx,esi,edi 中,当系统调用完成之后,返回值可以在寄存器 eax 中获得。
  • Linux 采用的是 C 语言的调用模式,这就意味着所有参数必须以相反的顺序进栈,即最后一个参数先入栈,而第一个参数则最后入栈。

转载于:https://www.cnblogs.com/lxq20135309/p/5296439.html

LINUX内核分析第四周——扒开系统调用的三层皮相关推荐

  1. Linux内核设计第四周——扒开系统调用三层皮

    Linux内核设计第四周 --扒开系统调用三层皮 一.知识点总结 (一).系统调用基础知识 1.用户态和内核态 内核态:在高级别的状态下,代码可以执行特权指令,访问任意的物理地址:  用户态:在相应的 ...

  2. 第四周—扒开系统调用的“三层皮”

    [洪韶武 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ]  第四周 扒开系统 ...

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

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

  4. 作业4:扒开系统调用的三层皮(上) 20135115臧文君

    扒开系统调用的三层皮(上) 注:作者:臧文君,原创作品转载请注明出处,<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000 ...

  5. linux内核分析——扒开系统调用的三层皮(上)

    20135125陈智威 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 系统调用 ...

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

    黄胤凯   原创作品转载请注明出处   <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.视频学习 1 ...

  7. 扒开系统调用的三层皮(下)

    5234+ 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1.给MenuO ...

  8. Linux内核分析——第五章 系统调用

    第五章 系统调用 5.1 与内核通信 1.系统调用在用户空间进程和硬件设备之间添加了一个中间层,该层主要作用有三个: (1)为用户空间提供了一种硬件的抽象接口 (2)系统调用保证了系统的稳定和安全 ( ...

  9. Linux内核分析(七)系统调用execve处理过程

    本文的内容包括: 1. 用execve系统调用加载和执行一个可执行程序的代码演示 2. 用gdb跟踪系统调用execve的执行过程 3. execve系统调用处理过程分析 一.如何用execve系统调 ...

最新文章

  1. 精通android布局,Android精通:View与ViewGroup,LinearLayout线性布局,RelativeLayout相对布局,ListView列表组件...
  2. snoopy(强大的PHP采集类) 实例应用
  3. 不是你无法入门自然语言处理(NLP),而是你没找到正确的打开方式
  4. Hadoop hdfs 使用流来上传文件代码示例
  5. app 访问h5 如何截取_微信H5支付申请相关问题
  6. [Linux] 编写Dockerfile文件自动构建镜像
  7. QT中父子窗口事件传递与事件过滤器
  8. Jsoup V的幕后秘密:优化的技巧和窍门
  9. The Closest M Points BZOJ 3053
  10. Java7并发编程指南——第一章:线程管理
  11. PREV-52 小数第n位 (大数)
  12. mysql 数据入库去重_MySQL中去重 distinct 的用法 ,数据库去重distinct
  13. 单龙芯3A3000-7A1000PMON研究学习-(28)撸起袖子干-再来一杯代码10-内存初始化1
  14. 如何解决竞价推广中的恶意点击?
  15. 阿里云API网关配置详解
  16. 在python中实现输出易经六十四卦
  17. 编程之美--1的数目
  18. 华铸DCcae80 铸铝 压铸软件.rar
  19. docker基础手册
  20. 互联网大厂Java岗考点(阿里+百度+腾讯+字节跳动+美团+京东)

热门文章

  1. CTFshow 爆破 web27
  2. 图像去噪 使用dct变换进行去噪
  3. canny算子的运用
  4. pytorch tensor查找0_在PyTorch中Tensor的查找和筛选例子
  5. 整数的幂计算(三种方法)最快O(logn)
  6. 14.4 线程通讯-生产者与消费者
  7. 11.1自定义异常类
  8. mysql如何配置hbm.xml_配置数据库映射文件hbm.xml
  9. 利用GPU训练网络时遇到的一些问题
  10. P3225 [HNOI2012]矿场搭建