20135323符运锦----第五周:扒开系统调用的“三层皮”(下)
扒开系统调用的“三层皮” (下)
一、知识总结
1.在MenuOS中通过添加代码增加自定义的系统调用命令
本周从内核态出发研究系统调用,通过跟踪调试,首先把上周的两个命令加到MenuOS中:
rm menu -rf 强制删除原menu文件
git clone https://github.com/mengning/menu.git 从github中克隆,更新menu代码到最新版
cd menu 进入menu
make rootfs 运行自动编译脚本,生成根文件系统,启动MenuOS
之后在main函数中增加MenuConfig,增加对应的time和time-asm函数(就是上周写的两个函数)。最后,再make rootfs (rootfs是一个脚本,可以自动生成,编译)。
2.使用gdb跟踪调试内核
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:单步运行
3.系统调用在内核代码中的工作机制和初始化 (总结)###
过程:int 0x80触发一个系统调用 ->执行系统调用处理函数system_call ->返回到用户态。详细过程见上周博客http://www.cnblogs.com/20135323fuyunjin/p/5277375.html
中断向量int 0x80 ->system_call,初始化时绑定,系统调用号将xyz和中断服务程序sys_xyz关联起来。
系统调用机制的初始化
\arch\x86\kernel\traps.c代码中定义了系统调用的初始化。
\init\main.c start_kernel
trap_init();//main.c中start_kernel函数
\arch\x86\kernel\traps.c
#ifdef CONFIG_X86_32
set_system_trap_gate(SYSCALL_VECTOR//系统调用的中断向量, &system_call//汇编代码入口);
set_bit(SYSCALL_VECTOR, used_vectors);
#endif
理解system_call到iret之间的主要代码
系统调用返回前可能进行进程调用,里面会发生进程上下文的切换。
从系统调用入口开始:ENTRY(system_call)
SAVE_ALL //保存现场
system_call:
call *system_call_table(,%eax,4) //调用了系统调用处理函数,有系统调用号eax中,是实际的系统调用处理程序
work_notifysig //处理pending信号
work_resched:call schedule //调用完会跳转到restore_all
restore_all //恢复现场
INTERRUPT_RETURN //irp_return宏,中断处理过程在这结束
sys_exit_work//没有这个就restore_all,返回用户态。一旦进入sys_exit_work:会有一个进程调度时机。
简化了一下代码,如下图:
从以上可以看出:在系统调用返回之前,可能发生进程调度,进程调度里就会出现进程上下文的切换;进程间通信可能有信号需要处理。
二、实验
1.先执行rm menu -rf,强制删除原有的menu文件夹,使用git命令更新menu代码至最新版
2.增加对应的两个函数,Getpid和Getpidasm ,main函数中增加对应两个函数####
3.输入help,可以看到当前的系统调用并使用
4.使用gdb调试
三、分析从system_call开始到iret结束之间的整个过程并画出流程图
【符运锦 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000】