第五节 系统调用的三个层次(下) ——20135203齐岳
2016-03-25 17:27
183 查看
第五节 系统调用的三个层次(下)
By 20135203齐岳
本周的课程主要内容有三点:在MenuOS中通过添加代码增加自定义的系统调用命令
使用gdb跟踪调试内核
简单分析system_call代码了解系统调用在内核代码中的处理过程
由于本周实验是在Kali虚拟机上进行操作的,具体实现过程中的代码和实验楼里的环境有一定的差异,在解决了各种报错之后终于完成了实验,在这次的实验报告中将较为详细的记录实验过程中遇到的问题以及解决方案,以便以后更加熟练地理解与掌握Kali的操作原理和步骤。
实验——分析system_call中断处理过程
给MenuOS增加time和time-asm命令
在源代码中增加getpid和getpid-asm的代码Kali虚拟机中menu文件夹存放的目录为/home/YL/menu,打开目录即可看到内核相关代码,通过vim test.c指令打开并编辑源代码,在其中加入自定义添加的函数代码,如下图所示。
在main函数中增加MenuConfig
在main函数中添加对应的函数调用代码,格式与代码中原有的函数调用格式保持一致。
make rootfs(将分步编译的过程编写在脚本当中自动生成)
进行这一步的时候无论是使用make rootfs脚本编译还是make all都会出现错误:Nothing to be done,make clean指令也无效。其原因是该文件目录下有一个名为rootfs的文件夹,导致编译失败,删除该文件夹后即可成功编译,结果如下图所示。
使用gdb跟踪系统调用内核函数sys_time
启动内核到调试状态qemu-system-x86_64 -kernel bzImage -initrd /home/YL/rootfs.img -S -s
重新启动一个终端进行调试
在内核中加载符号表:
file /usr/src/linux-source-4.4/vmlinux
由于Kali是64位机所以要进行设置否则会报错"Remote 'g'packet reply is too long"。
set arch i386:x86-64
之后使用1234端口连接并开始调试。运行结果如下图所示。
设置断点并单步跟踪调试
注意不能在start _ kernel处设置断点因为此时还没有完整设置好64位的运行环境,因此无法设置断点进行调试。
s单步执行,sys _ getpid 函数返回之后进入汇编代码处理,gdb无法继续跟踪,在sys _ call处设置断点也无法停下来调试。
系统调用在内核代码中的处理过程
系统调用在内核代码中的工作机制和初始化
系统调用的工作机制具体内容见上周实验报告:http://www.cnblogs.com/July0207/p/5277774.html
系统调用机制的初始化
\init\main.c start _ kernel中调用了trap _ init()函数。
\arch\x86\kernel\traps.c代码中定义了系统调用的初始化。
#ifdef CONFIG_X86_32 set_system_trap_gate(SYSCALL_VECTOR, &system_call); //系统调用的中断向量和system_call的入口。一旦执行0x80,系统就自动跳转到system _call执行 set_bit(SYSCALL_VECTOR, used_vectors); #endif
分析system_call伪代码
ENTRY(system_call) #0x80的下一条 指令 RING0_INT_FRAME # can't unwind into user space anyway ASM_CLAC pushl_cfi %eax # save orig_eax SAVE_ALL # 保存系统寄存器信息 GET_THREAD_INFO(%ebp) # 获取thread_info结构的信息 # system call tracing in operation / emulation testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) # 测试是否有系统跟踪 jnz syscall_trace_entry # 如果有系统跟踪,先执行,然后再回来 cmpl $(NR_syscalls), %eax # 比较eax中的系统调用号和最大syscall,超过则无效 jae syscall_badsys # 无效的系统调用 直接返回 syscall_call: call *sys_call_table(,%eax,4) # 调用实际的系统调用程序 syscall_after_call: movl %eax,PT_EAX(%esp) # 将系统调用的返回值eax存储在栈中 syscall_exit: LOCKDEP_SYS_EXIT DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt TRACE_IRQS_OFF movl TI_flags(%ebp), %ecx testl $_TIF_ALLWORK_MASK, %ecx # 判断当前的任务是否需要进程调度 jne syscall_exit_work # 未完成,则去执行这些任务 restore_all: TRACE_IRQS_IRET # iret 从系统调用返回
系统调用流程分析
参考资料
【原创作品转载请注明出处】 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000相关文章推荐
- Qt Quick App的两种启动模式
- js抛物线动画——加入购物车动效
- 贪心1006
- hdu 2874(LCA + 节点间距离)
- Android4.42-Setting源码分析之蓝牙模块Bluetooth(下)
- JVM调优总结:一些概念
- PowerDesigner表创建脚本双引号问题
- 分析JAVA应用CPU占用过高的问题
- tomcat性能调优
- [C#]C++与C#数据类型总结
- (p226)最长单调递增子序列
- 【慕课笔记】2-2 数据类型与操作数据表—数据类型之整形
- 初探Java8中的HashMap(转)
- “单例”的属性访问器
- 对于EL表达式和ONGL表达式区别的相关理解
- shell中exit命令不退出脚本
- android蓝牙技术
- 使用SOAPUI测试WEBAPI接口
- Hibernate缓存问题
- java反射获取字段以及获取字段值和设置字段值