《Linux内核分析》第四周 扒开系统调用的“三层皮”
【刘蔚然 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000】
WEEK FOUR(3.14——3.20)扒开系统调用的“三层皮”
SECTION 1 用户态、内核态和中断处理过程
1.用户态、内核态区别
- 在高级别的状态下,代码可以执行特权指令,访问任意的物理地址;
- 在相应的低级别执行状态下,代码的掌控范围会受到限制。
- 为什么会有这种级别划分?
- 没有访问权限划分容易使得系统混乱(毕竟普通程序员写的函数可能会有明显的疏漏)
- Intel x86 CPU有四种不同的执行级别0——3,Linux只是用了其中的0和3来表示内核态和用户态
- 如何区分?CPU每条指令都是通过cs:eip这两个寄存器读取的(代码段选择寄存器:偏移量寄存器)。一般在Linux中,0xc0000000以上的地址(指的是逻辑地址)空间只能在内核态下访问(即全部的4G内存都可以访问)
- 如何联系?中断处理是从用户态进入内核态的主要方式。系统调用是一种特殊的中断。
2.中断处理
- 中断指令会在寄存器上保存一些寄存器的值放入内核堆栈,比如:用户态栈顶地址(ss:esp),标志寄存器(eflags),cs:eip(为了返回的时候popl弹出保存的返回地址)。同时,将相关联的中端服务历程的入口加载到cs:eip,把当前的堆栈段esp也加载到CPU里面
- (
)
- 中断发生之后第一件事就是保存现场;同样,中断处理结束前的最后一件事情就是恢复现场。也就是说,SAVE ALL之后就是内核态了;restore all之后再返回用户态。
SECTION 2 系统调用概述和系统调用的三层皮
1.系统调用概述
- (
)
- 解释:系统调用减少了系统与硬件之间的耦合,所以极大提高了系统可移植性
- 操作系统提供的API和系统调用的关系
- (
)
- (
)
- 解释:libc库定义的API使得程序员不用去以汇编代码进行系统调用而是直接以函数调用的形式。
- (
2.系统调用的三层皮
- (
)
- 系统调用的三层皮:xyz,systemcall,sysxyz。也就是:API,中断向量,服务程序
3.系统调用的参数传递方法(难点)
- (
)
- (
)
- 补充解释:
- 系统调用号将xyz和sys_xyz关联起来;
- 为什么把eax寄存器的值设置为2?
- 参考http://www.cnblogs.com/bastard/archive/2012/08/31/2664896.html
- 这句话的意思是举例说明eax的作用,即:fork()通过系统调用创建与原进程几乎一样的进程。在进行系统调用之前就把NRfork(也就是2)传给eax
- 参数超过6个怎么办?
- 把某一个寄存器作为一个指针,指针会指向一个地址空间,把其他参数放在这里;这样内存也可以访问。
SECTION 3 使用库函数API和C代码中嵌入汇编代码触发系统调用
1.使用库函数API获取当前系统时间(这算是一个比较简单的系统调用)
代码:
time.c
#include <stdio.h>
#include <time.h>
int main()
{
time_t tt;//int型数值
struct tm *t;
tt = time(NULL);
t = localtime(&tt);//强制类型转换,便于输出
printf("time:%d:%d:%d:%d:%d:%d:\n",t->tm_year+1960,t->tm_mon,t->tm_mda,t->tm_hour,t->tm_min,t->tm_sec);
return 0;
}
编译:
gcc time.c -o time -m32
结果:
打印出的就是系统时间下的 年:月:日:时:分:秒
2.C代码中嵌入汇编代码的复习
- (
)
- 汇编代码就相当于一个函数
3.用汇编方式触发系统调用获取系统当前时间
代码:
time_asm.c
#include <stdio.h>
#include <time.h>
int main()
{
time_t tt;//int型数值
struct tm *t;
asm volatile(
"mov $0,%%ebx\n\t"//系统调用传递第一个参数使用ebx,这里是null
"mov $0xd,%%eax\n\t"//传递系统调用号13(16进制即0xd)
"int $0x80\n\t"
"mov %%eax,%0\n\t"//通过eax这个寄存器返回系统调用值,和普通函数一样
:"=m"(tt)
);
t = localtime(&tt);
printf("time:%d:%d:%d:%d:%d:%d:\n",t->tm_year+1960,t->tm_mon,t->tm_mda,t->tm_hour,t->tm_min,t->tm_sec);
return 0;
}
编译和结构和上面的代码是一样的。
这段代码让我们更清楚地知道用户态对内核态做了什么
实验
以C语言和嵌入式汇编两种方式编写通过API进行系统调用的实例
【分析:本次实验虽然有一部分的自主性,但总体来说不难;只要能够理解上面两段代码的“本质”——对API的使用,就可以很容易地进行编写】
过程:
- 根据系统调用表,选取27号系统调用alarm(之前对此函数有所了解,主要是在和sleep搭配使用的方面) ;
- 查阅、复习alarm()函数的作用和用法。参考http://www.linuxidc.com/Linux/2012-07/66837.htm;
- alarm函数不同于例子中的time()函数,前者是有参数的(参数代表的是定时器数值),所以,相较于C语言代码而言,嵌入式汇编就要复杂一点了。
- 进行C语言代码实例编写:
- 代码:
- (
)
- 编译过程&结果:
- (
)
- 进行嵌入式汇编代码编写:
- 代码(尝试):
- (
)
- 编译出错,其实是我没有加""导致的,改过之后如下:
- (
)
- 解释:在给出的例子中,我看到ebx这个寄存器是作为第一个参数传递使用的(当然,time()函数没有参数,传进去的是0也就是null),所以我在想这个看似“多此一举”的步骤应该是用来传递函数参数的。在这里,我将参数3的值传给了ebx;
- 结果:
- (
)
《Linux内核分析》第四周 扒开系统调用的“三层皮”的更多相关文章
- 20135327郭皓--Linux内核分析第四周 扒开系统调用的三层皮(上)
Linux内核分析第四周 扒开系统调用的三层皮(上) 郭皓 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/U ...
- LINUX内核分析第四周——扒开系统调用的三层皮
LINUX内核分析第四周--扒开系统调用的三层皮 李雪琦 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course ...
- linux内核分析 第四周 扒开系统调用的三层皮(上)
一.用户态.内核态和中断处理过程 系统调用是用户通过库函数方式:库函数帮我们把系统调用封装起来. 内核态:高级别执行,可以使用特权指令,访问任意的物理地址. 用户态:低级别执行,代码范围受到限制. C ...
- Linux内核分析 笔记五 扒开系统调用的三层皮(下) ——by王玥
(一)给MenuOs增加time和time-asm命令 更新menu代码到最新版 在main函数中增加MenuConfig 增加对应的Ttime和TimeAsm函数 make rootfs (二)使用 ...
- Linux内核及分析 第四周 扒开系统调用的三层皮(上)
实验过程 选择20号系统调用getpid(取得进程识别码) 在网上查询getpid函数的C语言代码以及其嵌入式汇编语句 C语言代码: #include <stdio.h> #include ...
- Linux内核设计第四周——扒开系统调用三层皮
Linux内核设计第四周 ——扒开系统调用三层皮 一.知识点总结 (一).系统调用基础知识 1.用户态和内核态 内核态:在高级别的状态下,代码可以执行特权指令,访问任意的物理地址: 用户态:在相应的低 ...
- linux 内核 第四周 扒开系统调用的三层皮 上
姬梦馨 原创作品 http://mooc.study.163.com/course/USTC-1000029000 一.用户态.内核态和中断处理过程 用户通过库函数与系统调用联系起来:库函数帮我们把系 ...
- Linux内核分析——第四周学习笔记20135308
第四周 扒开系统调用的“三层皮” 一.内核.用户态和中断 (一)如何区分用户态.内核态 1.一般现在的CPU有几种不同的指令执行级别 ①在高级别的状态下,代码可以执行特权指令,访问任意的物理地址,这种 ...
- LINUX内核分析第四周学习总结——扒开系统调用的“三层皮”
LINUX内核分析第四周学习总结--扒开系统调用的"三层皮" 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>MOOC ...
随机推荐
- javascript拾掇
用javascript如何给span赋值呢?一般有两种方法: 1>输出html <body onload="s()"><span id="hell ...
- BZOJ1858[Scoi2010]序列操作 题解
题目大意: 有一个01序列,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0:1 a b 把[a, b]区间内的所有数全变成1:2 a b 把[a,b]区间 ...
- BZOJ3631[JLOI2014]松鼠的新家 题解
题目大意: 给你一棵树,要从编号为a[1]的节点走到编号为a[2]的节点再走到编号为a[3]的节点……一直走到编号为a[n]的节点.问每个节点最少访问多少次. 思路: 将其进行轻重链剖分,则从a[i] ...
- Redis的两个小技巧
1.通配删除相同前缀的缓存 DEL命令的参数不支持通配符,但我们可以结合Linux的管道和xargs命令自己实现删除所有符合规则的键. 比如要删除所有以“structure_”开头的键,就可以执行下面 ...
- 洛谷 P1074 靶形数独 Label:search 不会
题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的 ...
- 【BZOJ】3434: [Wc2014]时空穿梭
http://www.lydsy.com/JudgeOnline/problem.php?id=3434 题意:n维坐标中要找c个点使得c个点在一条线上且每一维的坐标单调递增且不能超过每一维限定的值m ...
- 【noiOJ】p1794
t1794:集合加法 查看 提交 统计 提问 总时间限制: 3000ms 内存限制: 65536kB 描述 给出2个正整数集合A = {pi | 1 <= i <= a},B = {q ...
- ffmpeg解码
解码流程 http://www.cnblogs.com/lidabo/p/4582391.html 例子 http://www.cnblogs.com/lidabo/p/4582393.html
- Hightcharts设置Y轴最大最小值
有两种方法: 1:是在控件初始化时预设, yAxis: [{ max:}] 2:在程序运行中动态更新设置 thChart.yAxis[].update({ min: , max: });
- Java生成CSV文件实例详解
本文实例主要讲述了Java生成CSV文件的方法,具体实现步骤如下: 1.新建CSVUtils.java文件: package com.saicfc.pmpf.internal.manage.utils ...