郑斌 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
实验要求:
- 使用gdb跟踪分析一个系统调用内核函数(您上周选择的那一个系统调用),系统调用列表参见http://codelab.shiyanlou.com/xref/linux-3.18.6/arch/x86/syscalls/syscall_32.tbl ,推荐在实验楼Linux虚拟机环境下完成实验。
- 根据本周所学知识分析系统调用的过程,从system_call开始到iret结束之间的整个过程,并画出简要准确的流程图,撰写一篇署名博客,并在博客文章中注明“真实姓名(与最后申请证书的姓名务必一致) + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”,博客内容的具体要求如下:
- 题目自拟,内容围绕系统调用system_call的处理过程进行;
- 博客内容中需要仔细分析system_call对应的汇编代码的工作过程,特别注意系统调用返回iret之前的进程调度时机等。
- 总结部分需要阐明自己对“系统调用处理过程”的理解,进一步推广到一般的中断处理过程。
实验环境:
本次实验在实验楼Linux虚拟机环境进行。
实验内容:
1.按照视频的教程,把上周的系统调用函数getpid()和getpid_asm()添加到内核中。
过程如下图所示:
打开menu中的 test.c文件,添加如下代码
1 int Getpid(int argc , char * argv[]) 2 { 3 int pid; 4 pid=getpid(); 5 printf("pid=%d\n",pid); 6 return 0; 7 } 8 9 int Getpidasm(int argc , char *argv[]) 10 { 11 int pid; 12 asm volatile( 13 "mov $0,%%ebx\n\t" 14 "mov $0x14,%%eax\n\t" 15 "int $0x80\n\t" 16 "mov %%eax, %0\n\t" 17 :"=m"(pid) 18 ); 19 printf("pid = %d\n",pid); 20 return 0; 21 }
并在main函数中添加
重新make 后。可以看到menuOS有了getpid的命令,功能为返回当前进程的标识。
通过试验可以看到,系统中已经成功添加了该函数调用功能。
下面对该程序进行调试分析,了解系统调用的过程。
其中部分命令为:
qemu -kernel linux.3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 调试。
file linux-3.18.6/vmlinux 加载调试内核符号表。
b 设置断点 n 单步执行
我们分别在start_kernel ,systemy_call , sys_getpid.添加断点并执行观察,list查看附近的代码。
(>﹏<)本人水平有限,我真的有很努力的看啊,分析啊,可是还是不太懂啊(╯^╰)
接下来我们对系统调用过程中system_call到iret之间的调用进行分析。
这部分menuOS还不能使用gdb调试,主要为参考老师讲课内容,以及/linux-3.18.6/arch/x86/kernel/entry_32.S,和一些网上资料。
其中在上面的syscall_exit_work可以分析看到 执行workpend过程中,可能会有新的userspace。
我的理解为系统调用过程中可能产生其他优先级更高的中断,CPU先去执行新的更高优先级中断程序执行完毕后再回来执行当前的系统调用。
所以会产生嵌套调用。 具体其中的过程,由于本人时间和能力分析有限,有不对的大神们多多指教。
当执行返回后会resotre_all 恢复中断现场,相关参数等。
实验总结:
通过 int $0x80 产生系统调用,根据系统调用号参数执行具体的系统调用程序。
本次实验主要是学习了系统调用过程中的sys_call的内部执行机制,虽然分析的很浅显,但还是很好的帮助提高了对这部分的linux内核机制运行的理解。
实验开始过程中添加自己写的系统调用到menuOS搞了好久,是太粗心写过代码了,要静下心来认真点啊。