Linux第五周学习总结——扒开系统调用的三层皮(下)
作者:刘浩晨
【原创作品转载请注明出处】 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
一、给MenuOS增加time和time-asm命令
1. 克隆并自动编译MenuOS
- rm menu -rf 强制删除原menu文件
- git clone http://github.com/mengning/menu.git 从github中克隆
2. test.c中main函数里,增加MenuConfig
3. 增加函数:
对应的两个函数:Time和TimeAsm。在下图中可以看到有了这两个调用
4.make rootfs
二、使用gdb跟踪系统调用内核函数sys_time
调试:qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
gdb命令:
• file linux-3.18.6/vmlinux:加载符号表
• target remote:1234:连接到需要调试的menuos里
• b sys_time:在系统调用time的位置设置断点
• c:在MenuOs里使用time,停在断点处
• s:如果但单步执行就会进入schedule函数
• finish:执行完整个函数
三、系统调用在内核代码中的处理过程
执行完int 0x80后从system_call开始:
另外还有:
• SAVE_ALL:保存现场
• call *sys_call_table(,%eax,4)调用了系统调度处理函数,eax存系统调用号,是实际的系统调度程序。
• sys_call_table:系统调用分派表
• syscall_after_all:保存返回值
• sys_exit_work里有进程调度时机,若无sys_exit_work,就执行restore_all恢复,返回用户态。
• work_pending -> work_notifysig,用来处理信号
• call schedule:进程调度代码
• restore_all:恢复现场。
• INTERRUPT_RETURN(iret):结束。
注意:在系统调用返回之前,可能会发生进程调度,当前进程间可能有信号需要处理。
四、实验——分析system_call中断处理过程
继续使用上次实验选择的getuid,代码:
int Getuid(int argc ,char *argv)
{
pid_t uu;
uu=getuid();
printf("uu = %d \n", uu);
return 0;
}
int GetuidAsm(int argc ,char *argv)
{
pid_t uu;
uu = getuid();
asm volatile(
"mov $0x24,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax,%0\n\t"
:"=m"(uu)
);
printf("uu = %d \n",uu);
return 0;
}
步骤:
1.先rm menu -rf强制删除原有的menu文件夹,使用git命令更新menu代码至最新版。
2.在test.c中增加Getuid()和GetuidAsm()函数
3.make rootfs自动编译生成根文件系统
4.调试:
5.设置断点:
6.单步运行直至finish运行到最后