Linux系统调用------追踪系统调用的执行过程

王雪 原创作品转载请注明出处 《Linux内核分析》MOOC课程 http://mooc.study.163.com/course/USTC-1000029000

一、基础知识
关于系统调用
系统调用号:内核为每个系统调用定义了一个唯一的编号,这个编号定义在…/include/asm/unisd.h中(最大为NR_syscall)
系统调用表:同时在内核中保存了一张记录系统调用号和其对应服务例程的表,与系统调用表一一对应
在系统调用陷入内核之前,需要把系统调用号一起传入内核,这个标号就是系统调用表的sys_call _ table 下标,这个传递的动作是通过int 0x80int 0 x80前,将系统调用号保存到eax的寄存器中
这里写图片描述
系统调用表记录了各个系统调用的服务例程的入口地址,以系统调用号为偏移量找到对应的处理函数地址,执行处理函数。
这里写图片描述
处理函数结束后,转入ret _ from _ sys _ call ()例程,系统调用返回到用户态
以上便是系统调用的处理过程。
如果我们想在自己的系统里添加自己的自定义的系统调用需要4步:
(1)添加系统调用号(unistd.h中)
(2)在系统调用表中添加对应表项
(3)实现系统调用的服务例程
(4)重新编译内核,启动新内核


二、实验内容
(1)向实验楼下Linux-3.18.6的MenuOS菜单中添加time系统调用
这里写图片描述
为什么open失败呢,因为!在qemu模拟器中,没有文件!!!
(2)跟踪系统调用的过程
进入gdb调试:
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 冻结qemu,已将cpu冻结
另开一个shell窗口:
(gdb)file linux-3.18.6/vmlinux
(gdb)target remote:1234
(gdb)break start_kernel
(gdb)c
可以看见系统启动时停止在start_kernel处
这里写图片描述
在系统调用time的内核处理函数sys_time处添加断点,执行n,将MenuOS系统启动起来,这时我们执行time,系统停在断点sys _time处。
这里写图片描述
我们并不能利用gdb跟踪到sys_time里面的具体执行过程
这里写图片描述


(3)查看系统调用的实现代码
1.系统调用机制是什么时候初始化的:
在系统启动时执行start_kernel,start _kernel中会调用trap _init()函数, 用于硬件中断向量初始化,这个函数被定义在/arch/x86/kernel/trap.c中,
这里写图片描述
SYSCALL_VECTOR系统中断向量
system_call:系统调用入口,
当发生中断或系统调用,直接找到system_call入口地址去执行。
2.系统调用的处理过程:
系统调用的定义在/arch/x86/kernel/entry_32.S中,有一个入口
ENTRY(system_call),是int $0x80后的下一条执行地址,
大致流程:
这里写图片描述
system _ call->sys call _table ->syscall exit(是否处理syscall _ exit _ work) ->restort _all -> irq _return,work _notifying用于处理信号
在系统调用返回前有可能进行进程调度,有可能需要处理当前进程的信号
进行进程调用在work_resched中call schedule;
这里写图片描述
中断结束后,从内核态返回用户态!
二、实验总结
这次实验主要是分析了系统是怎么响应一个系统调用的,系统调用的执行过程,代码的执行过程等知识,是理解操作系统工作的重要步骤!

展开阅读全文

没有更多推荐了,返回首页