20252803《Linux内核原理与分析》第六周作业

作业要求

阅读学习教材「庖丁解牛Linux 操作系统分析 」第6章,有问题优先使用chatgpt等AI工具。或者到蓝墨云班课中提问,24小时内回复,鼓励解答别人问题,提问前请阅读「如何提问」。
教材深入学习关注豆列「Linux内核及安全」。
学习蓝墨云班课中第六周视频「扒开系统调用的三层皮?(下)」,并完成实验楼上配套实验五。,注意从下往上看。基于树莓派或其他平台完成ARM相关内容。
作业标题 “学号《Linux内核原理与分析》第X周作业”,重点是遇到的问题和解决方案内容涵盖教材学习和视频,提交格式用Markdown,同时提交转换的 PDF(VSCode 有相关插件)。

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

1、使用 gdb 跟踪分析一个系统调用内核函数(您上周选择的那一个系统调用),系统调用列表参见 torvalds/linux。推荐在实验楼 Linux 虚拟机环境下完成实验。
2、根据本周所学知识分析系统调用的过程,从 system_call 开始到 iret 结束之间的整个过程,并画出简要准确的流程图,撰写一篇署名博客

一、重新定义系统调用getpid和getppid

进入实验楼,与上周操作相同,重新编译内核后,进入menu界面下,编辑test.c。

cd ~/LinuxKernel
rm -rf menu
git clone https://github.com/mengning/menu.git
cd menu
vim test.c

在这里插入图片描述

在test.c中加入上一实验的的getpid和getppid代码,并在test.c中的main函数中加入两个MenuConfig函数进行这两个系统调用函数的配置:

int _20252803_main1(){
        pid_t pid=getpid();
        pid_t ppid=getppid();
        printf("pid=%d  ppid=%d\n",pid,ppid);
}

int _20252803_main2() {
    pid_t pid, ppid;
    
    asm volatile("mov $0x14, %%eax\n\t"  // getpid 的ID为20
                 "int $0x80\n\t"
                 "mov %%eax, %0\n\t"
                 : "=r" (pid) :: "%eax");

    asm volatile("mov $0x40, %%eax\n\t"  // getppid 的ID为64
                 "int $0x80\n\t"
                 "mov %%eax, %0\n\t"
                 : "=r" (ppid) :: "%eax");

    printf("pid=%d  ppid=%d\n", pid, ppid);

    return 0;
}

在这里插入图片描述
两个配置系统调用函数的MenuConfig函数如下:

 MenuConfig("getpid1","system_call_1",_20252803_main1);
 MenuConfig("getpid_asm_2","system_call_asm_2",_20252803_main2);

在这里插入图片描述

二、make rootfs自动编译脚本:

在这里插入图片描述

三、使用 gdb 跟踪分析getpid和getppid系统调用内核函数

先启动冻结的内核,再另打开一个shell,进行GDB调试,建立GDB和gdbserver之间的连接。
冻结命令如下:

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

在这里插入图片描述

gdb调试命令如下:

gdb  file linux-3.18.6/vmlinux

gdb  target remote:1234

gdb b sys_getpid

在这里插入图片描述
在这里插入图片描述

四、分析整个过程,并画出简要准确的流程图

1、用户态触发系统调用(陷入前)

准备工作:用户程序通过寄存器传递参数,将系统调用号存入 eax 寄存器(x86 架构)。
触发中断:执行 int $0x80(x86 传统)或 syscall(x86_64 现代)指令,触发软件中断。
CPU 自动操作:切换特权级(用户态 CPL=3 → 内核态 CPL=0)。硬件自动保存用户态关键上下文(cs、eip、eflags 寄存器入栈)。

2、进入内核态:system_call 入口

跳转入口:CPU 自动跳转到内核预设的中断处理入口 system_call(位于 arch/x86/kernel/entry_32.S 或 entry_64.S)。
保存完整上下文:内核手动将用户态寄存器(ebx、ecx、edx 等)压入内核栈,防止被内核操作覆盖。
合法性检查:验证系统调用号(eax)是否在允许范围内(≤ NR_syscalls),若非法则跳转至错误处理(返回 -ENOSYS)。

3、执行系统调用处理函数

查表映射:通过系统调用号(eax)查询系统调用表(如 sys_call_table),找到对应的内核处理函数(如 sys_getpid)。
执行操作:调用该函数完成具体功能(如获取进程 ID),将返回值存入 eax 寄存器。

4、系统调用返回前处理

信号检查:执行 syscall_exit 逻辑,检查用户态程序是否有未处理的信号。
信号处理:若有信号,先跳转至用户态的信号处理函数,处理完成后回到系统调用流程。

5、内核态返回用户态

恢复上下文:从内核栈弹出之前保存的用户态寄存器(ebx、ecx 等)。
执行返回指令:通过 iret(x86)或 sysret(x86_64)指令,CPU 自动完成:从栈中恢复用户态 cs、eip、eflags 寄存器。切换特权级(内核态 CPL=0 → 用户态 CPL=3)。
用户态续行:用户程序从 int $0x80 或 syscall 的下一条指令继续执行,通过 eax 获取返回值。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值