LINUX内核分析第四周——扒开系统调用的三层皮
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内核分析第四周——扒开系统调用的三层皮相关推荐
- Linux内核设计第四周——扒开系统调用三层皮
Linux内核设计第四周 --扒开系统调用三层皮 一.知识点总结 (一).系统调用基础知识 1.用户态和内核态 内核态:在高级别的状态下,代码可以执行特权指令,访问任意的物理地址: 用户态:在相应的 ...
- 第四周—扒开系统调用的“三层皮”
[洪韶武 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ] 第四周 扒开系统 ...
- 《Linux内核分析》 第四节 扒开系统调用的三层皮(上)
<Linux内核分析> 第四节 扒开系统调用的三层皮(上) 张嘉琪 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com ...
- 作业4:扒开系统调用的三层皮(上) 20135115臧文君
扒开系统调用的三层皮(上) 注:作者:臧文君,原创作品转载请注明出处,<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000 ...
- linux内核分析——扒开系统调用的三层皮(上)
20135125陈智威 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 系统调用 ...
- 《Linux内核分析》 第四节 扒开系统调用的三层皮(上)
黄胤凯 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.视频学习 1 ...
- 扒开系统调用的三层皮(下)
5234+ 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1.给MenuO ...
- Linux内核分析——第五章 系统调用
第五章 系统调用 5.1 与内核通信 1.系统调用在用户空间进程和硬件设备之间添加了一个中间层,该层主要作用有三个: (1)为用户空间提供了一种硬件的抽象接口 (2)系统调用保证了系统的稳定和安全 ( ...
- Linux内核分析(七)系统调用execve处理过程
本文的内容包括: 1. 用execve系统调用加载和执行一个可执行程序的代码演示 2. 用gdb跟踪系统调用execve的执行过程 3. execve系统调用处理过程分析 一.如何用execve系统调 ...
最新文章
- 精通android布局,Android精通:View与ViewGroup,LinearLayout线性布局,RelativeLayout相对布局,ListView列表组件...
- snoopy(强大的PHP采集类) 实例应用
- 不是你无法入门自然语言处理(NLP),而是你没找到正确的打开方式
- Hadoop hdfs 使用流来上传文件代码示例
- app 访问h5 如何截取_微信H5支付申请相关问题
- [Linux] 编写Dockerfile文件自动构建镜像
- QT中父子窗口事件传递与事件过滤器
- Jsoup V的幕后秘密:优化的技巧和窍门
- The Closest M Points BZOJ 3053
- Java7并发编程指南——第一章:线程管理
- PREV-52 小数第n位 (大数)
- mysql 数据入库去重_MySQL中去重 distinct 的用法 ,数据库去重distinct
- 单龙芯3A3000-7A1000PMON研究学习-(28)撸起袖子干-再来一杯代码10-内存初始化1
- 如何解决竞价推广中的恶意点击?
- 阿里云API网关配置详解
- 在python中实现输出易经六十四卦
- 编程之美--1的数目
- 华铸DCcae80 铸铝 压铸软件.rar
- docker基础手册
- 互联网大厂Java岗考点(阿里+百度+腾讯+字节跳动+美团+京东)