2020-2021-1 20209326 《Linux内核原理与分析》第六周作业

作业信息

这个作业属于哪个课程 <2020-2021-1Linux内核原理与分析)>
这个作业要求在哪里 <2020-2021-1Linux内核原理与分析第六周作业>
这个作业的目标 <使用gdb跟踪分析一个系统调用内核函数>
作业正文 <本博客链接>

一、实验内容

1. 给MenuOS增加命令

修改test.c文件,新增creat功能。

rm -rf menu
git clone https://github.com/mengning/menu.git
cd menu


make rootfs

2. 用GDB来跟踪系统调用内核的函数sys_time

//启动内核
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage/ -initrd rootfs.img -S -s     
//新打开一个shell窗口,启动gdb
file linux-3.18.6/vmlinux
target remote:1234
//加入断点
b start_kernel//代码会在start_kernel()处停下来
b sys_time    //调试time系统调用
b sys_creat   //调试creat系统调用



查看了linux-3.18.6/fs/open.c和linux-3.18.6/kernel/time/time.c文件。因为系统调用是用宏来定义的,所以无法直接调试。

3.在linux-3.18.6/arch/x86/kernel/entry_32.S查看system_call源码

一旦执行int 0x80,CPU就直接跳转到system_call这个位置来执行,即系统调用的工作机制在start_kernel这里初始化之后,CPU一遇到int 0x80就会立即跳转到sys_call的位置,system_call中断服务程序的入口这段会变代码的处理过程是非常重要的,它是系统调用的处理过程,而系统调用是一个特殊的中断,在中断过程中有保护现场和恢复现场,这段代码里面同样也有保护现场SAVE_ALL和恢复现场restore_all的过程。

	# system call handler stub
ENTRY(system_call)
	RING0_INT_FRAME			# can't unwind into user space anyway
	ASM_CLAC
	pushl_cfi %eax			# save orig_eax//保存系统调用号
	SAVE_ALL                        //保存现场,将用到的所有CPU寄存器保存到栈中
	GET_THREAD_INFO(%ebp)           //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        //检查系统调用号(系统调用号应小于NR_syscalls)
	jae syscall_badsys               //不合法,跳入异常处理
syscall_call:
	call *sys_call_table(,%eax,4)    //合法,对照系统调用号在系统调用表中寻找相应的系统调用的内核处理函数
syscall_after_call:
	movl %eax,PT_EAX(%esp)		# store the return value//保存返回值到栈中
syscall_exit:
	LOCKDEP_SYS_EXIT
	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
					# setting need_resched or sigpending
					# between sampling and the iret
	TRACE_IRQS_OFF
	movl TI_flags(%ebp), %ecx
	testl $_TIF_ALLWORK_MASK, %ecx	# current->work//检查是否需要处理信号
	jne syscall_exit_work            //需要,进入 syscall_exit_work

restore_all:
	TRACE_IRQS_IRET                  //不需要,执行restore_all恢复,返回用户态
restore_nocheck:
	RESTORE_REGS 4			# skip orig_eax/error_code
irq_return:
	INTERRUPT_RETURN                  //相当于iret

二、总结

1.系统调用过程

2.系统调用处理过程的理解
通过本实验的学习,知道了:系统调用时,首先通过save_all来保存现场,然后进行系统调用,并将返回值放入寄存器eax中,然后确认有没有其他的中断进入,以便设置返回信号。如果没有就从系统调用返回,并通过函数restore_all恢复现场;如果有就进入函数syscall_exit_work,查看有没有挂起的任务,有就转入函数work_pending进行任务调度,没有就返回,并恢复现场。

posted @ 2020-11-13 21:11  20209326  阅读(109)  评论(0编辑  收藏  举报