张文俊+ 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
学习总结
1、给MenuOS增加time和time-asm命令
首先,将time这两个文件添加到MenuOS里面,需要以下指令:
rm menu -rf //其中,-rf为强制删除命令
然后通过以下指令重新克隆一个menu:
git clone https://github.com/mengning/menu.git
然后按照之前的课程编译启动MenuOS。
进入MenuOS后,关键是查看GetPid和GetPidAsm两个命令。
总结来说,给MenuOS增加GetPid和GetPidAsm两个命令,需要按照四个步骤:
(1)更新menu代码到最新版
(2)在main函数中增加MenuConfig
(3)增加对应的GetPid函数和GetPidAsm函数
(4)make rootfs
2、如何调试time——使用gdb跟增系统调用内核函数sys_time
首先,使用-s -S命令进行调试:
进入gdb后,将vmlinux加载进来:
加载进之后,链接Target remote 1234,链接到需要调试的MenuOS:
对sys_time设置断点:
现在c运行之后,系统会启动,MemuOS正常启动。如果这时执行time命令,会发现它卡住了:
list可以查看内部代码,如果这里一直按s单步执行,会进入schedule函数。
sys_time返回后进入汇编代码处理gdb无法继续追踪。
3、系统调用在内核代码中的工作机制和初始化
主要分析从system_call到返回的整个过程。
首先,了解系统调用机制的初始化:
其中,在start_kernel的trap_init里,我们可以看到设计了一个trap_gate函数。
syscall_vector是系统调用中断向量,system_call是汇编代码的入口。
因此,初始化的结果是:这时代码中一旦执行int0X80,CPU就会直接跳转到system_call这个位置上。
system_call之后的指令入口如下:
从上述代码开始分析:
系统调用也是一种中断,也存在保护现场(SAVE_ALL)和恢复现场(RESTORE_ALL)的问题。
下面,sys_call_table调用系统调度表,其中eax传递系统调用号,找到对应的系统调用(在老师的例子里就是sys_time)。
然后执行syscall_after_call,保存返回值eax;继续执行syscall_exit,查看是否需要跳转到syscall_exit_work。不需要的话,就恢复现场,然后返回结束。
如果需要跳转到syscall_exit_sork,则执行work_pending,其中包含work_notifysig,是处理信号的。
可以执行work_resched,是处理重新调度的。
然后恢复并返回结束。
流程图示:
内核:很多种不同的中断处理过程的集合。