20135201李辰希 《Linux内核分析》第五周 扒开系统调用的“三层皮”(下)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20135201李辰希 《Linux内核分析》第五周 扒开系统调用的“三层皮”(下)相关的知识,希望对你有一定的参考价值。
李辰希 原创作品转载请注明出处 《Linux内核分析》
MOOC课程http://mooc.study.163.com/course/USTC-100002900
一.给MenusOS增加time和time-asm命令
1.操作步骤
进入实验楼
- 首先,强制删除当前的menu
-
克隆一个新的menu
-
进入menu之后,输入make rootfs,就可以自动编译
- 输入help,可以发现系统支持更多的命令:
- help
- version
- quit
- time
- time-asm
- 那么,time和time-asm是如何实现的呢?
- 进入test.c之后,查看main函数。与之相关的只有两条语句:
- menuconfig("time","Show system Time",Time);
- menuconfig("time-asm","Show system Time",Time(asm));
6.给MenuOS增加time和time_asm命令的步骤:
- 更新menu代码到最新版
- test.c中main函数里,增加MenuConfig()
- 增加对应的Time函数和TimeAsm函数
- make rootfs
二.使用gdb跟踪系统调用内核函数sys_time
1.操作步骤
-
进入内核,冻结启动
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
- 启动gdb)
- 加载debug版本内核并连接到target地址)
- 为处理time函数的系统调用systime设置断点之后,在menuOS中执行time。发现系统停在systime处。继续按n单步执行,会进入schedule函数。
- sys_time返回之后进入汇编代码处理,gdb无法继续跟踪
- 如果在syscall设置断点(entry32.S),然后输入c之后,发现是不会在sys_call处停下来的(因为这里是一处系统调用函数而不是正常函数)
代码如下:
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
gdb (gdb)file linux-3.18.6/vmlinux //加载符号表
(gdb)target remote:1234 //连接
b sys_time:在系统调用time的位置设置断点
c:继续执行,停在断点处
n/s:单步运行,s进入函数,n不进入
理解system_call到iret之间的主要代码
系统调用返回前可能进行进程调用,里面会发生进程上下文的切换。
从系统调用入口开始:ENTRY(system_call)
SAVE_ALL //保存现场
system_call:
call *system_call_table(,%eax,4)
//调用了系统调用处理函数,有系统调用号eax中,是实际的系统调用处理程序。
当前任务syscall_exit_work里面有work_pending里面有
work_notifysig //处理pending信号,不用管
重要的是work_resched:call schedule //决定了进程调度的代码,调用完会跳转到restore_all
restore_all //恢复现场
INTERRUPT_RETURN //irp_return宏,中断处理过程在这结束
三、系统调用在内核代码中的处理过程
1.int 0x80指令与systemcall是通过中断向量联系起来的,而API和对应的sys[函数]是通过系统调用号联系起来的
2.系统调用机制的初始化
- trapgate函数中,涉及到了系统调用的中断向量和systemcall的汇编代码入口;一旦执行int 0x80,CPU直接跳转到system_call
3.简化后便于理解的system_call伪代码
- int 0x80后的下一条指令从此处的ENTRY(system_call)开始
- 系统调用返回之前可能会发生进程调度(call schedule)
- 当前进程可能有信号需要处理(work_notifysig)
- 进程调度中会发生中断上下文切换和进程上下文的切换,这是个连贯的过程
- 内核可以抽象成多种不同中断处理过程的集合
4.简单浏览system_call到iret之间的主要代码
- SAVE_ALL:保存现场
- syscall_call:调用了系统调用处理函数
- restore all:恢复现场(因为系统调用处理函数也算是一种特殊的“中断”)
- syscallexitwork:如3.中所述
- INTERRUPT RETURN:也就是iret,系统调用到此结束
四、总结
阐明自己对“系统调用处理过程”的理解。
系统调用是一种特殊的中断。它是写一个函数,它需要用到内核中的代码,但这部分代码我没有办法直接访问,所以,我通过系统调用,它说它帮我去让内核执行我想执行的代码,把最后的结果告诉我。这时,我作为用户就是什么都不知道了,等着系统调用来告诉我结果。系统调用,它先通过sys_ call这个函数和内核沟通,说我想用一下你的sys_ xxx功能,请你把这个功能执行的结果告诉我。内核很快就去自己的内部,执行sys_ xxx的功能,执行完了之后,内核告诉了系统调用,这个函数的执行结果。最后系统调用就通过iret指令将结果信息反馈给了用户。这样,用户就完美的在请求系统调用帮助后,轻松的解决了问题。
以上是关于20135201李辰希 《Linux内核分析》第五周 扒开系统调用的“三层皮”(下)的主要内容,如果未能解决你的问题,请参考以下文章
20135201李辰希《Linux内核分析》第三次 构造一个简单的Linux系统OS
20135201李辰希 《Linux内核分析》第四周 扒开系统调用的“三层皮”