Linux内核分析之扒开系统调用的三层皮(下)
一、实验内容
1. 通过内核的方式使用系统调用
需要使用的命令
rm menu -rf //强制删除当前menu
git clone http://github.com/mengning/menu.git //重新克隆新版本的menu
cd menu
ls
make rootfs //rootfs是事先写好的一个脚本,自动编译自动生成根文件系统,同时自动启动MenuOS
2. 将上周选择的系统调用添加到MenuOS中
打开menu中的 test.c文件,添加Gitpid和Gitpidasm代码
int Getpid(int argc , char * argv[])
{
int pid;
pid=getpid();
printf("pid=%d\n",pid);
return ;
} int Getpidasm(int argc , char *argv[])
{
int pid;
asm volatile(
"mov $0,%%ebx\n\t"
"mov $0x14,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax, %0\n\t"
:"=m"(pid)
);
printf("pid = %d\n",pid);
return ;
}
在main函数中添加
MenuConfig(“getpid","Show pid",Getpid);
MenuConfig("getpid-asm","Show pid(asm)",Getpidasm);
重新make 后。可以看到menuOS有了getpid的命令,功能为返回当前进程的标识。
3.使用gdb跟踪分析这该系统调用内核函数
系统中已经成功添加了该函数调用功能。然后对该程序进行调试分析,使用gdb跟踪分析这该系统调用内核函数。
需要使用命令为
qemu -kernel linux.3.18./arch/x86/boot/bzImage -initrd rootfs.img -s -S 调试。 file linux-3.18./vmlinux 加载调试内核符号表。 b 设置断点 n 单步执行
二、系统调用过程分析
1. 系统调用在内核代码中的工作机制和初始化
int 0x80——>system call:通过中断向量匹配
system call——>sys_xyz():通过系统调用号匹配
一旦执行int 0x80后立刻跳转到system_call执行
2. 系统调用system_call的处理过程
syscall_call 函数到系统调用服务例程通过系统调用号联系起来:在上面执行软中断 0x80 时,系统调用号会被放入eax寄存器(参数的传递),system_call 函数读取eax寄存器获取参数(当前系统调用的调用号),将其乘以4生成偏移地址。然后以中断向量表(sys_call_table)为基址,以系统调用号所确定的为偏移地址相加得到最后的物理地址:基址+偏移地址 => 系统调用服务例程的地址。其中 sys_call_table 基址在文件 arch/x86/kernel/syscall_table_32.S 中定义,同时表中每一项例程的地址占用4个字节,所以上面乘以4。
由于系统调用例程在定义时时用 asmlinkage 标记了的,所以编译器仅从堆栈中获取该函数的参数。在进入system_call函数前,用户应用会把参数存放到寄存器中,system_call 函数执行时会首先把这些寄存器压入堆栈。这样对系统调用服务例程可以直接从堆栈照片能够获取参数。
3.从system_call开始到iret结束之间的过程
从整体过程来看,系统通过 int 0x80 从用户态进入内核态。在这个过程中系统先保存了中断环境,然后执行系统调用函数。system_call() 函数通过系统调用号查找系统调用表 sys_cal_table 来查找到具体的系统调用服务进程。在执行完系统调用后在执行 iret 之前,内核做了一系列检查,用于检查是否有新的中断产生。如果没有新的中断,则通过已保存的系统中断环境返回用户态。这样就完成了一个系统调用过程。系统调用通过 INT 0x80 进入内核,跳转到 system_call() 函数,然后执行相应服务进程。因为代表了用户进程,所以这个过程并不属于中断上下文,而是属于进程上下文。
4.系统调用处理过程的汇编代码分析
.macro INTERRUPT_RETURN ; 中断返回
iret
.endm
.macro SAVE_ALL ; 保护现场
...
.macro RESTORE_INT_REGS
...
.endm ENTRY(system_call)
SAVE_ALL
syscall_call:
call *sys_call_table(,%eax,)
movl %eax, PT_EAX(%esp) ; store the return value
syscall exit:
testl $_TIF_ALLWORK_MASK, %ecx # current->work
jne syscall_exit_work
restore_all:
RESTORE_INT_REGS
irq_return:
INTERRUPT_RETURN
ENDPROC(system_call) syscall_exit_work:
testl $_TIF_WORK_SYSCALL_EXIT, %ecx
jz work_pending
END(syscall_exit_work) work_pending:
testb $_TIF_NEED_RESCHED, %cl
jz work_notifysig
work_resched:
call schedule
jz restore_all
work_notifysig:
... ; deal with pending signals
END(work_pending)
无论是中断返回(ret_from_intr) ,还是系统调用返回,都使用了 work_pending 和resume_userspace。对于宏SAVE_ALL来说,这条语句会把将寄存器的值压入堆栈当中,压入堆栈的顺序对应struct pt_regs ,出栈时,这些值传递到struct pt_regs的成员,实现从汇编代码向C程序传递参数。struct pt_regs可以在arch/x86/include/asm/ptrace.h中查看。用户态到内核态需要int 0x80进行中断,只有生成了中断向量后才可以切换状态。中断处理让CPU停止当前工作转为执行系统内核中预设的一些任务,因此必须要对当前CPU执行的任务进行执行现场的保护工作,并对一些其他工作进行检查,完成调用后,再进行检查,才能执行iret返回。系统内部调用涉及CPU架构等内容,不同的CPU对于系统调用的汇编具体代码是不一样的。
三、总结
(1)open 函数通过系统调用号与 sys_open 系统调用服务例程函数联系起来
(2)int 0x80 通过中断向量(0x80)与 system_call 联系起来的
(3)系统调用中断本质上是一个保存当前工作状态,然后处理,最后返回并且恢复进程的过程
刘帅
原创作品转载请注明出处
《Linux内核分析》MOOC课程
Linux内核分析之扒开系统调用的三层皮(下)的更多相关文章
- 《Linux内核分析》--扒开系统调用的三层皮 20135311傅冬菁
扒开系统调用的三层皮 20135311傅冬菁 一.内容分析 寄存器上下文(从用户态切换到内核态) 中断/int指令会在堆栈上保存一些寄存器的值(用户态栈顶地址..当时的状态字.当下 ...
- Linux内核分析之扒开系统调用的三层皮(上)
一.原理总结 本周老师讲的内容主要包括三个方面,用户态.内核态和中断,系统调用概述,以及使用库函数API获取系统当前时间.系统调用是操作系统为用户态进程与硬件设备进行交互提供的一组接口,也是一种特殊的 ...
- 《Linux内核分析》-- 扒开系统调用的三层皮(下)之system_call中断处理过程 20135311傅冬菁
20135311傅冬菁 原创作品 <Linux内核分析>MOOC课程 分析system_call中断处理过程 内容分析与总结: 系统调用在内核代码中的工作机制和初始化 系统调用在用户态中 ...
- linux 内核 第四周 扒开系统调用的三层皮 上
姬梦馨 原创作品 http://mooc.study.163.com/course/USTC-1000029000 一.用户态.内核态和中断处理过程 用户通过库函数与系统调用联系起来:库函数帮我们把系 ...
- 《Linux内核分析》第四周 扒开系统调用的“三层皮”
[刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK FOUR( ...
- 《Linux内核分析》第五周 扒开系统调用的三层皮(下)
[刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK FIVE( ...
- LINUX内核分析第五周学习总结——扒开系统调用的“三层皮”(下)
LINUX内核分析第五周学习总结--扒开系统调用的"三层皮"(下) 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>M ...
- 《Linux内核分析》第五周学习总结 扒开系统调用的三层皮(下)
扒开系统调用的三层皮(下) 郝智宇 无转载 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.给Men ...
- 《Linux内核分析》 第四节 扒开系统调用的三层皮(上)
<Linux内核分析> 第四节 扒开系统调用的三层皮(上) 张嘉琪 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com ...
随机推荐
- Android 4.0 源代码结构
Android源码的第一级目录结构 Android/abi (abi相关代码.ABI:application binary interface,应用程序二进制接口) Android/bioni ...
- java序列化深拷贝
java深拷贝 序列化和反序列化合成在一起的方法CloneUtils import java.io.ByteArrayInputStream; import java.io.ByteArrayOutp ...
- HDMI学习
市面上大多4K显示器都配备了HDMI 1.4接口,仅能实现30Hz的刷新率,不足以带来流畅的显示效果, 酱紫情况,就算是搭配了HDMI 2.0高清线也是无法发挥其作用.只有更先进的HDMI 2.0标准 ...
- 一天一经典Reducing the Dimensionality of Data with Neural Networks [Science2006]
别看本文没有几页纸,本着把经典的文多读几遍的想法,把它彩印出来看,没想到效果很好,比在屏幕上看着舒服.若用蓝色的笔圈出重点,这篇文章中几乎要全蓝.字字珠玑. Reducing the Dimensio ...
- 关于monkeyrunner的一些初步理解性的题目
1.Monkeyrunner中包含几个基本类?分别大概的作用是什么? Monkeyrunner中基本包含了MonkeyRunner,MonkeyDevice,MonkeyImage MonkeyRun ...
- 使用mysql 命令行,增加 ,删除 字段 并 设置默认值 及 非空
使用mysql 命令行,增加 ,删除 字段 并 设置默认值 及 非空 添加 alter table table_name add field_name field_type; 添加,并设置默认值,及非 ...
- 关于spring boot jar包与war包的问题
此文为转载:http://mrlee23.iteye.com/blog/2047968 在开发调试完成之后,可以将应用打成JAR包的形式,在Eclipse中可以直接使用Maven插件的package命 ...
- 【Lua】Lua的几点优化原则
Lua是一门以性能著称的脚本语言,被广泛的应用在很多方面,比如很多游戏的插件. 很多时候,没有必要去考虑性能的问题,不过,如果我们在开始编写代码的时候就以更适当,性能更高的方式与结构去组织代码,对于程 ...
- pxe无人值守安装多网卡注意事项
pxe无人值守安装linux配置这里就不说了,直接看这篇博客http://www.cnblogs.com/mchina/p/centos-pxe-kickstart-auto-install-os.h ...
- Redis与Memcached的区别
传统MySQL+ Memcached架构遇到的问题 实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量 ...