作业信息
这个作业属于哪个课程 | <2020-2021-1Linux内核原理与分析)> |
---|---|
这个作业要求在哪里 | <2020-2021-1Linux内核原理与分析第六周作业> |
这个作业的目标 | <使用gdb跟踪分析一个系统调用内核函数> |
作业正文 | 本博客链接 |
实验过程
向MenuOS中添加命令
删除并重新git新版本的menu文件夹
修改相应的test.c文件,添加相应的getPid命令
使用make rootfs重新编译生成镜像
打开系统进行测试
使用gdb进行调试
源码分析
在linux-3.18.6/arch/x86/kernel/entry_32.S中可以查看到system_call的汇编源码:
ENTRY(system_call)
RING0_INT_FRAME
ASM_CLAC
pushl_cfi %eax
SAVE_ALL
GET_THREAD_INFO(%ebp)
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(NR_syscalls), %eax
jae syscall_badsys
syscall_call:
call *sys_call_table(,%eax,4)
syscall_after_call:
movl %eax,PT_EAX(%esp)
syscall_exit:
LOCKDEP_SYS_EXIT
DISABLE_INTERRUPTS(CLBR_ANY)
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
testl $_TIF_ALLWORK_MASK, %ecx
jne syscall_exit_work
restore_all:
TRACE_IRQS_IRET
restore_all_notrace:
movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
movb PT_OLDSS(%esp), %ah
movb PT_CS(%esp), %al
andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
CFI_REMEMBER_STATE
je ldt_ss
#endif
restore_nocheck:
RESTORE_REGS 4
irq_return:
INTERRUPT_RETURN
系统进入系统调用时(system_call),会首先保存现场,执行save_all宏,然后进行调用中断服务程序syscall_call,接着执行syscall_exit,当执行到这里准备退出时,会进行判断需不需要响应其他中断或者信号,如果不需要则直接进行restore_all恢复现场并且irq_return,正式返回到系统调用的地方;如果需要响应其他中断,则需要执行syscall_exit_work,看看有没有work_resched或者work_notifysig,看看当前进程需不需要调度,如果需要就执行call_schedule,如果需要响应某个信号,则进行work_notifysig,接着再跳转至restore_all接着执行并退出。这个就是系统调用时汇编代码级别的大致执行过程。具体可以按流程图: