Linux操作系统分析学习总结

Linux操作系统分析中的学习收获和感想

此次课程中学习到很多Linux操作系统的相关知识,对Linux有了更深入的了解。课程中报名参加了大赛,然而因为时间和水平的原因,没有完成相应任务入围,因此简单讲一下学习收获以及实验情况。

这门课学习了x86和ARM64指令集架构,具体包括寄存器布局和指令集,并进行C代码编译成RISC-V汇编代码后执行步骤分析。具体可见这个帖子

印象比较深刻的还有中断、进程方面的内容。
中断可分为外部中断和内部中断,其中内部中断主要是在用户进程执行时,硬件中断信号到达,导致进入内核态,执行对应的中断服务程序,内部中断主要是包括故障和陷阱两部分。
中断过程如下:
中断处理是从用户态进入内核态的主要方式。中断发生后,从用户态切换到内核态:
在当前进程的内核态堆栈中保存:当前进程的用户态栈顶地址、当时的状态字、当时的寄存器的值。
(1) 中断发生后的第一件事情就是保存现场
(2)将当前进程的内核态的栈顶地址、内核态的状态字放入CPU对应的寄存器中,并将寄存器的值指向中断处理函数的入口(对系统调用而言,是指向system_call)
(3)当中断处理结束后,查看是否发生进程调度:
如果没有发生进程调度:则恢复中断现场,返回到原来的状态,也就是将中断时保存在当前进程内核态中的信息进行出栈操作到当前CPU中。
如果发生进程调度:当前的这些状态都会保存在系统内核堆栈里。
(4)恢复现场,将保存堆栈中的值,以及保存的程序计数器中的值,恢复到寄存器中。

总而言之,通过这次课程,让我对Linux有了一定的了解,非常感谢孟宁老师和李春杰老师的授课。

实验情况及对Linux操作系统的理解

实验在Ubuntu18.04环境下进行。

wget https://raw.github.com/mengning/mykernel/master/mykernel-2.0_for_linux-5.4.34.patch
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
patch -p1 < ../mykernel-2.0_for_linux-5.4.34.patch
sudo apt install build-essential gcc-multilib
sudo apt install qemu # install QEMU
sudo apt install libncurses5-dev bison flex libssl-dev libelf-dev
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 here 和 my_timer_handler here。通过mymain.c和 myinterrupt.c 程序可以看出 mymain.c 通过每次计数达到100000输出一次my_start_kernel here从而不停的执行。同时还具有一个中断处理程序的上下文环境,周期性的产生时钟中断信号,触发myinterrupt.c程序执行输出 my_timer_handler here。这样就通过Linux内核代码模拟了一个具有时钟中断和C代码执行环境的硬件平台。

在这里插入图片描述
制作根文件系统过程如下。
首先从https://www.busybox.net下载 busybox源代码解压,解压完成后,跟内核一样先配置编译,并安装。

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

在这里插入图片描述

然后编译安装,默认会安装到源码目录下的 _install 目录中。

make -j$(nproc) && make install

然后制作内存根文件系统镜像,大致过程如下:

mkdir rootfs
cd rootfs
cp ../busybox-1.31.1/_install/* ./ -rf
mkdir dev proc sys home
sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/

然后准备init脚本文件放在根文件系统跟目录下(rootfs/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

用以下命令启动虚拟机,可以看到启动后qemu就是停止的

qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s

在这里插入图片描述

加-nographic -append "console=ttyS0"参数启动不会弹出QEMU虚拟机窗口,可以在纯命令行下启动虚拟机

qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s -nographic -append "console=ttyS0"

再打开一个窗口,启动gdb,把内核符号表加载进来,建立连接:

cd linux-5.4.34/
gdb vmlinux
(gdb) target remote:1234
(gdb) b start_kernel

#gdb调试常用参数
r(run)开始运行程序;
c(continue)继续运行一直到断点停止
b(break)设置程序断点;
p(print)打印出变量值;如 p var,会把var变量的值输出
s(step)单步跟踪,会进入函数内部
n(next)单步跟踪,不进入函数
finish跳出函数调试,并打印返回时的信息
u(until)跳出循环体
q(quit)退出gdb
l(list)显示当前行后面的源程序
bt (backtrace)查看堆栈信息
info查看各类gdb信息以及环境信息,比如:info break 可以查看断点信息
clear清除全部已定义的断点
delete删除指点的断点号,后面接断点号

在这里插入图片描述
start_kernel就像是c代码中的main函数,大部分模块的初始化工作都是在start_kernel中完成的。在start_kernel()中Linux将完成整个系统的内核初始化。内核初始化的最后一步就是启动init进程这个所有进程的祖先。start_kernel()是内核的汇编与C语言的交接点,在该函数以前,内核的代码都是用汇编写的,完成一些最基本的初始化与环境设置工作。在start_kernel的最后,是调用rest_init函数,在rest_init函数,内核将使用下面的代码产生第一个真正的进程,即pid=1的1号进程。

参考资料

庖丁解牛Linux操作系统分析https://gitee.com/mengning997/linuxkernel

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值