作业5:扒开系统调用的三层皮(下) 20135115臧文君

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

注:作者:臧文君,原创作品转载请注明出处,《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

一、给MenuOS增加time和time-asm命令

1、先将menu强制删除:rm menu -rf

2、重新克隆一个新版本的menu:

git clone https://github.com/mengning/menu.git

注:linux系统已是最新版,不需重新克隆。

3、cd menu,查看ls,make rootfs可以自动生成根文件系统并启动MenuOS。

4、help查看命令:

5、如何添加:

(1)vi test.c,在main函数中加入三行MenuConfig的代码。

 

(2)增加对应的Time函数、TimeAsm函数和MyIdle函数。

 

 

(3)make rootfs

二、使用gdb跟踪系统调用内核函数sys_time

1、先进入usr/src/linux-source-4.4/arch/x86_64/boot路径下,然后启动内核并冻结:qemu-system-x86_64 -kernel bzImage -initrd /home/YL/menu/rootfs.img -s -S

 

2、水平分割,启动gdb,加载符号表file:

gdb /usr/src/linux-source-4.4/vmlinux

注:gdb vmlinux = gdb,再file vmlinux

 

由于kali是64位机,所以需要设置set arch i386:x86-64,否则会报错“Remote ‘g’packet reply is too long:”

3、连接target remote:1234,设置断点break sys_time,按C继续执行。

 

4、在qemu窗口中输入time命令,在gdb窗口中list查看代码。

 

5、按n/s进行单步执行,会进入schedule函数,finish将函数全部执行完。sys_time返回后进入汇编代码处理gdb无法继续跟踪。

6、执行int 0x80后执行system_call对应的代码,设置断点后再执行,并不能停在system_call的位置。

三、系统调用在内核代码中的处理过程

1、系统调用在内核代码中的工作机制和初始化

(1)xyz()和sys_xyz()通过系统调用号匹配起来,int 0x80和system_call通过中断向量匹配起来。

(2)系统调用机制的初始化:trap_init();

 

2、简化后便于理解的system_call伪代码

int 0x80的下一条指令是ENTRY(system_call),是中断系统调用的处理过程。

 

 

sys_call_table(,%eax,4)系统调用表,括号里传递的是系统调用号,整个调用的是sys_time。

简化后的伪代码:

 

 

 

关键信息:

1)在系统调用返回之前,可能会发生进程调度call schedule;

2)在当前进程有可能需要处理进程间通信的信号work_pending。

3、将system_call到iret之间的处理过程画成流程图

 

4、中断上下文的切换和进程上下文的切换

内核提供的服务在返回到用户态之前可能会发生进程调度,进程调度的里面就存在进程上下文的切换。

内核就是很多不同的中断处理过程的集合。

5、简单浏览system_call到iret之间的主要代码

SAVE_ALL:保存现场。

syscall_call:sys_call_table:调用系统调用处理函数。

iret:中断系统调用过程结束。

总结:

这两周我们完整的学习了系统调用的知识,系统调用实际上就是一种特殊的中断。

在系统调用时,我们需要保存现场:SAVE_ALL,用于保存系统调用时的上下文。接着,根据eax传入的系统调用号,通过sys_call_table查询到调用的系统调用,然后跳转相应的系统调用处理函数后,进行处理。最后,调用restore_all恢复系统调用时的现场,并用iret返回用户态。

原文地址:https://www.cnblogs.com/CatherineZang/p/5327039.html