Linux课程总结
本学期,在linux操作系统分析这门课中,老师首先详细的从多个方面为我们展现了Linux操作系统中的方方面面。李春杰老师主要讲解了进程管理、文件系统管理、中断与异常发生的始终等几个方面。让整个Linux更加完整而清晰的展现在了我们的面前。
这其中给我印象最深刻的部分便是中断异常的处理了。这一部分在408中曾经粗浅的学习过一些,但是在这门课上,李春杰老师从不同的角度进行了更加深入的分析,使我对于这部分知识有了更加深刻的了解。从前我认为中断只是进行了简单的设备和CPU之间的通信,在学完了这门课后我认识到了我知识的不完整。
首先是中断的产生部分,中断控制器监视IRQ线,接受引发信号;将信号转换为对应的中断向量(一个数),通过INTR引脚发送,产生中断,并维持电压等待CPU的应答。这是CPU将会得到中断向量,读IDTR寄存器都确定指向IDT表的第i项,读GDTR寄存器获得GDT的基地址,找到IDT表项中的段选择符标识的段描述符,在判断中断合法后进行下一步操作。CPU将会检查进入中断的进程当前状态,根据内核态和用户态的不同来进行操作。如果是从用户态进入的,将会开启新的内核态堆栈,保存相关寄存器的值,在这之后开始真正的处理中断。在处理程序执行完成后,会再此根据进入时的特权级进行不同的操作,来还原中断前的上下文,返回原来的特权等级。
不同于李春杰老师着重于对底层代码的梳理,孟宁老师更加着重与整个Linux运行的原理。孟宁老师从目前的操作系统生态环境入手,为我们展示了操作系统的发展历程,带我们看到了不同架构、不同时代的操作系统运行的差别,通过实际的代码为了们展示了ISA寄存器、操作系统寻址方式以及一些常用的指令。从较为宏观的角度出发,引领我们形成对Linux操作系统整体上的认识。
孟宁老师对于Linux系统中出现的函数调用情况的讲解,给我留下了深刻的印象。老师通过清晰明了的图像,为我们展现了函数调用时内存堆栈发生的变化。当发生函数调用时,首先系统会将新函数所调用的函数实参反向压栈,然后为恢复环境做准备,将当前的环境中存在的变量全部保存压栈。接下来保存函数的返回地址,当新函数执行完毕后程序将回到这个位置继续执行。然后用堆栈帧指针,多数情况下是ebp指向这里,接下来为新的函数预分配地址空间,使用栈顶指针指向新函数地址空间的最小值开始执行。对Linux系统函数调用的讲解,不仅帮助我更好的理解了Linux系统执行的原理,也帮助我更好的学习了其他课程。
实验一:mykernel
//下载mykernel2.0
wget https://raw.github.com/mengning997/mykernel/master/mykernel-2.0_for_linux-5.4.34.patch
//安装相关工具
sudo apt install axel
sudo apt install build-essential gcc-multilib
sudo apt install qemu-system-x86
sudo apt install libncurses5-dev bison flex libssl-dev libelf-dev
//下载内核源码,并解压
axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.34.tar.xz
xz -d linux-5.4.34.tar.xz
tar -xvf linux-5.4.34.tar
//在源码目录下进行后续操作,配置文件并编译
make defconfig # Default configuration is based on 'x86_64_defconfig'
make -j$(nproc)
qemu-system-x86_64 -kernel arch/x86/boot/bzImage
在qemu中可以看到my_start_kernel在执行,同时my_timer_handler在周期性执行

遇到的问题:一开始在gitee上下载的补丁,报错。后来改为github没有问题了
实验二:debug mykernel
首先需要在ubuntu上安装vscode,这里直接在商店中下载安装
安装调试工具
sudo apt install build-essential gcc-multilib
sudo apt install qemu # install QEMU
sudo apt install libncurses5-dev bison flex libssl-dev libelf-dev
下载源代码
sudo apt install axel
axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.34.tar.xz
xz -d linux-5.4.34.tar.xz
tar -xvf linux-5.4.34.tar
cd linux-5.4.34
这里借助一个 Python 脚本来生成 compile_commands.json 文件帮助Intellisense正常提示
python ./scripts/gen_compile_commands.py
配置内核选项
make defconfig # Default configuration is based on 'x86_64_defconfig'
make menuconfig
Kernel hacking —>
Compile-time checks and compiler options —>
[*] Compile the kernel with debug info
[*] Provide GDB scripts for kernel debugging
[*] Kernel debugging
# 关闭KASLR,否则会导致打断点失败
Processor type and features ---->
[] Randomize the address of the kernel image (KASLR)
编译内核
make -j2
生成根文件系统
axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2
tar -jxvf busybox-1.31.1.tar.bz2
cd busybox-1.31.1
make menuconfig
# 记得要编译成静态链接,不用动态链接库。
Settings --->
[*] Build static binary (no shared libs)
# 然后编译安装,默认会安装到源码目录下的 _install 目录中。
make -j$(nproc) && make install
制作内存根文件系统镜像
mkdir rootfs
cd rootfs
cp ../_install/* ./ -rf
mkdir dev proc sys home
sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/
准备init脚本放在根文件系统根目录下
touch init
#添加如下内容到init文件。
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
echo "Wellcome MengningOS!"
echo "--------------------"
cd home
/bin/sh
给init脚本添加可执行权限
chmod +x init
打包成内存根文件系统镜像
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz
测试挂载根文件系统,看内核启动完成后是否执行init脚本
qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz
命令行使用gdb调试内核
# 纯命令行下启动虚拟机
qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s -nographic -append "console=ttyS0"
cd linux-5.4.34/
gdb vmlinux
(gdb) target remote:1234
(gdb) b start_kernel
c、bt、list、next、step....

vscode调试内核
配置文件参考:https://github.com/mengning/linuxkernel/tree/master/src/kerneldebuging
断点可以设置在start_kernel中,然后Qemu开启GDB调试,vscode start debug就可以开始调试内核
本文回顾了Linux操作系统的关键概念和技术,重点介绍了进程管理、文件系统管理、中断处理等内容。通过对李春杰老师的课程学习,深入理解了中断异常处理机制;跟随孟宁老师的指导,掌握了Linux系统函数调用的工作原理。
440





