您的位置:首页 > 运维架构 > Linux

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

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

一、基础知识

关于系统调用

系统调用号:内核为每个系统调用定义了一个唯一的编号,这个编号定义在…/include/asm/unisd.h中(最大为NR_syscall)

系统调用表:同时在内核中保存了一张记录系统调用号和其对应服务例程的表,与系统调用表一一对应

在系统调用陷入内核之前,需要把系统调用号一起传入内核,这个标号就是系统调用表的sys_call _ table 下标,这个传递的动作是通过int 0x80实现的,在执行int 0 x80前,将系统调用号保存到eax的寄存器中



系统调用表记录了各个系统调用的服务例程的入口地址,以系统调用号为偏移量找到对应的处理函数地址,执行处理函数。



处理函数结束后,转入ret _ from _ sys _ call ()例程,系统调用返回到用户态

以上便是系统调用的处理过程。

如果我们想在自己的系统里添加自己的自定义的系统调用需要4步:

(1
a59a
)添加系统调用号(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;



中断结束后,从内核态返回用户态!

二、实验总结

这次实验主要是分析了系统是怎么响应一个系统调用的,系统调用的执行过程,代码的执行过程等知识,是理解操作系统工作的重要步骤!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: