2023-2024-1 20232816 《Linux内核原理与分析》第六周作业


分析system call中断处理过程

一、实验过程

1.打开实验楼虚拟机,输入以下命令

cd ~/LinuxKernel/
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img

结果如下图所示:
在这里插入图片描述
2.在test.c文件中增加Helloworld函数,删除一行多余的MenuConfig和在main函数中增加MenuConfig语句,编译并执行

int helloworld(int argc,char* argv[])
{
        char message[] = {"helloworld,20232816\n"};
        int length = 21;
        write(1,message,length);
        return 0;
}


在这里插入图片描述3.再次运行menu中添加了helloworld命令后,运行显示
在这里插入图片描述
4.使用gdb调试(之前课上做过)
条件变量以及打印。

在这里插入图片描述
行断点、函数断点、查看断点信息
在这里插入图片描述

使用 gdb 跟踪调试Linux内核的启动过程。在start_kernel、sys_time处设置断点。
在这里插入图片描述

二、实验分析

通过课本知识讲解明白了在 start_kernel 中的 trap_init()(定义在/arch/x86/kernel/traps.c中)里将中断向量0x80和system_call中断服务程序入口进行了绑定。

#ifdef CONFIG_X86_32
   set_system_trap_gate(SYSCALL_VECTOR, &system_call); //绑定中断向量0x80和system_call中断服务程序入口,其中SYSCALL_VECTOR定义为0x80
   set_bit(SYSCALL_VECTOR, used_vectors);
#endif

system_call中断服务程序入口代码如下:

ENTRY(system_call)
	RING0_INT_FRAME			#can't unwind into user space anyway
	ASM_CLAC
	pushl_cfi %eax			#保存系统调用号
	SAVE_ALL				#保存现场,将CPU寄存器保存在堆栈中
	GET_THREAD_INFO(%ebp)	#ebp用于存放当前进程thread_info结构的地址
	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)			#保存返回值到栈中
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	#检查是否有任务需要处理
	jne syscall_exit_work			#需要,进入 syscall_exit_work(最常见的进程调度时机)

restore_all:
	TRACE_IRQS_IRET			#恢复现场
restore_all_notrace:	
#ifdef CONFIG_X86_ESPFIX32
	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS, SS and CS
	# Warning: PT_OLDSS(%esp) contains the wrong/random values if we
	# are returning to the kernel.
	# See comments in process.c:copy_thread() for details.
	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			# returning to user-space with LDT SS
#endif
restore_nocheck:
	RESTORE_REGS 4			# skip orig_eax/error_code
irq_return:
	INTERRUPT_RETURN		#iret

流程图:
在这里插入图片描述

三、实验总结

在32位x86架构上,使用int 0x80指令进行系统调用。它将中断向量号0x80传递给处理器,从而触发内核中的中断处理程序。系统调用号(syscall number)存储在寄存器eax中。系统调用的参数存储在寄存器ebx、ecx、edx、esi、edi和ebp中。
执行系统调用后,返回值存储在eax寄存器中。在64位x86架构上,使用syscall指令进行系统调用。它通过相应的寄存器传递系统调用号和参数。系统调用号存储在rax寄存器中。系统调用的参数存储在rdi、rsi、rdx、r10、r8和r9寄存器中。
执行系统调用后,返回值存储在rax寄存器中。system call涉及syscall exit_work内部处理的一些关键点,大致的过程是syscall_exit_work需要跳转到work_pending,里面有 work notifysig 处理信号。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值