第五节 系统调用的三个层次(下)
2016-03-27 12:53
316 查看
第五节 系统调用的三个层次(下)
本周的课程主要内容有三点:在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处设置断点也无法停下来调试。
系统调用在内核代码中的处理过程
系统调用在内核代码中的工作机制和初始化
系统调用的工作机制系统调用机制的初始化
\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相关文章推荐
- Go语言学习(八)获取命令行参数
- xml解析代码示例
- IT十八掌作业_java基础第21天_mysql
- linux系统centOS7安装
- 《高质量C/C++编程》——重载覆盖与隐藏规则
- 威联通 移动硬盘路径 /share/USBDisk1
- Hadoop2.x配置HA
- 使用c3p0连接mysql数据库
- Carcraft
- 猜某个数的大小
- 解析rss和atom文件出现乱码问题
- IT十八掌作业_java基础第20天_断点续传、屏广软件
- 第四周项目5--用递归方法求解(2)
- 使用AccessKey作为用户身份标识信息
- 第五周实践项目2————游戏中的角色类(1)
- 如何解决XML文件中的警告提示“No grammar constraints (DTD or XML Schema) referenced in the document.”
- 第四次上机实践项目-项目1-三角形类锥形-(3)
- 小试循环(5)
- 中国剩余定理
- [python]“静态”变量:谈类属性和实例属性