(2023-2024-1)20232830《Linux内核原理分析与设计》第六周作业

(2023-2024-1)20232830《Linux内核原理分析与设计》第六周作业

1. 《庖丁解牛Linux分析》第6章

可执行程序工作原理

可执行程序工作原理
可执行程序工作原理
可执行程序工作原理
可执行程序工作原理
可执行程序工作原理

2. 实验五:分析 system_call 中断处理过程

2.1 gdb 跟踪分析系统调用内核函数

将上周实验函数 sysinfo 写入test.c文件中;
编辑test.c
编辑test.c
编译内核,看到添加的命令;
sysinfo
返回父目录,启动镜像,并冻结;
冻结
重新打开一个终端,打开gdb,并输入:

file linux-3.18.6/vmlinux
target remote:1234

接着我们设置两个断点,如下截图所示:
gdb
打开相应文件在相应的行找到相应的代码;
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结构的地址
					# 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_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

sys_getpid:

/**
 * sys_getpid - return the thread group id of the current process
 *
 * Note, despite the name, this returns the tgid not the pid.  The tgid and
 * the pid are identical unless CLONE_THREAD was specified on clone() in
 * which case the tgid is the same in all threads of the same group.
 *
 * This is SMP safe as current->tgid does not change.
 */
SYSCALL_DEFINE0(getpid)
{
	return task_tgid_vnr(current);
}

/* Thread ID - the internal kernel "pid" */
SYSCALL_DEFINE0(gettid)
{
	return task_pid_vnr(current);
}

/*
 * Accessing ->real_parent is not SMP-safe, it could
 * change from under us. However, we can use a stale
 * value of ->real_parent under rcu_read_lock(), see
 * release_task()->call_rcu(delayed_put_task_struct).
 */
SYSCALL_DEFINE0(getppid)
{
	int pid;

	rcu_read_lock();
	pid = task_tgid_vnr(rcu_dereference(current->real_parent));
	rcu_read_unlock();

	return pid;
}

SYSCALL_DEFINE0(getuid)
{
	/* Only we change this so SMP safe */
	return from_kuid_munged(current_user_ns(), current_uid());
}

SYSCALL_DEFINE0(geteuid)
{
	/* Only we change this so SMP safe */
	return from_kuid_munged(current_user_ns(), current_euid());
}

SYSCALL_DEFINE0(getgid)
{
	/* Only we change this so SMP safe */
	return from_kgid_munged(current_user_ns(), current_gid());
}

SYSCALL_DEFINE0(getegid)
{
	/* Only we change this so SMP safe */
	return from_kgid_munged(current_user_ns(), current_egid());
}

2.2 system_call开始至结束流程图

流程图

3. 总结

用户态进程调用 int 0x80 或 system_call 时,实际上触发了一个中断,这个中断使得 CPU 暂停当前进程的执行,保存当前执行环境(现场),并切换到内核态执行系统内核中预设的一些任务。这个过程确保了用户态进程在执行系统调用时能够以受控制的方式进入内核态,而系统调用执行结束后,再次保存当前执行环境,回到内核态,最终通过 iret 指令返回到用户态。

在这个过程中,中断处理程序会对调用的任务进行各种检查,包括参数的合法性、权限的验证等。然后,系统可能会进行进程调度,选择下一个要执行的任务。在系统调用执行完成后,还会进行进一步的检查,确保任务的正确执行。最后,通过 iret 指令返回到用户态,让用户态进程继续执行。这样的设计保证了系统调用的安全性和正确性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值