这个作业属于哪个课程 | <2020-2021-1Linux内核原理与分析)> |
---|---|
这个作业要求在哪里 | <2020-2021-1Linux内核原理与分析第六周作业> |
这个作业的目标 | <给MenuOS添加上周实现的系统调用、使用gdb分析sys_time执行过程、了解系统调用执行过程> |
作业正文 | <2020-2021-1 202029325 《Linux内核原理与分析》第六周作业> |
目录
一、实验过程
1.往MenuOS中添加命令
应实验要求,先删除之前的menu目录,再下载更新了版本之后的menu目录
-rm -rf menu
-git clone http://github.com/mengning/menu.git
进入menu目录之后,生成根目录系统,使用make rootf进入MenuOS,并使用help命令查看现有的命令
-make rootfs
-MenuOS>>help
然后给MenuOs添加上周编写的系统调用,代码如下:
int mygetpid(int argc,char* argv[]){
char message[] = {"hello world 20209325
"};
int length = 21;
write(1,message,length);
return 0;
}
使用MenuConfig将新的命令加入到MenuOs中:
-rootfs
-MenuOS>>help
-MenuOS>>mygetpid
添加成功如下图所示:
然后对结果进行make编译,结果如下:
2.使用gdb跟踪系统调用内核函数sys_time
进入到LinuxKernel目录,启动内核,并冻结
-cd LinuxKernel
-qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
接下来打开time.c文件查看
3.分析sys_time系统调用执行过程
在system_call处设置断点,查看system_call可知,它其实就是系统调用的处理过程,内部没有严格遵守函数调用堆栈基址,不支持gdb的调试,所以MenuOS中仍停留在sys_time
在linux-3.18.6/arch/x86/kernel/entry_32.s中找到system_call汇编代码并分析,如下:
二、实验收获
1.系统调用执行过程
2.system_call汇编代码分析
ENTRY(system_call)
RINGO_INT_FRAME
ASM_CLAC
push1_cfi %eax /*保存系统调用号*/
SAVE_ALL /*保存现场,将用到的所有CPU寄存器保存到栈中*/
GET_THREAD_INFO(%ebp) /*ebp用于存放当前进程thread_info结构的地址*/
test1 $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
jnz syscall_trace_entry
cmp1 $(nr_syscalls),%eax /*检查系统调用号(系统调用号应小于NR_syscalls)*/
jae syscall_badsys /*不合法,跳入异常处理*/
syscall_call:
call *sys_call_table(,%eax,4) /*合法,对照系统调用号在系统调用表中寻找相应的系统调用的内核处理函数*/
movl %eax,PT_EAX(%esp)/*保存返回值到栈中*/
syscall_exit:
testl $_TIF_ALLWORK_MASK, %ecx/*检查是否需要处理信号*/
jne syscall_exit_work /*需要,进入 syscall_exit_work*/
restore_all:
TRACE_IRQS_IRET /*不需要,执行restore_all恢复,返回用户态*/
irq_return:
INTERRUPT_RETURN /*相当于iret*/