为什么需要切换Linux内核为自定义参数版本
Linux内核是操作系统的核心,也是操作系统最基本的部分。Linux内核的体积结构是单内核的、但是他充分采用了微内核的设计思想、使得虽然是单内核、但工作在模块化的方式下、并且这个模块可以动态装载或卸载;Linux负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。如是我们在了解Linux内核的基础上根据自己的需要量身定制一个更高效,更稳定的内核,就需要我们手动去编译和配置内核里的各项相关的参数和信息了。
我的需求则是为了测试某个特定版本内核的性能,因此需要切换内核的版本。
我们有两个方法可以做到这点:
- 基于qemu的模拟
- 切换当前机器的内核版本
通过第一点我们可以运行起来一个简易的操作系统内核,但是它缺乏常见的库与程序,例如ls
, pwd
等的实现,尽管使用busybox可以帮助我们安装一些常用的库,但其在可用性上来说还是非常不足的。例如,用户无法自由地使用apt-get等包管理工具。
我们也可以彻底地更换当前机器上的内核版本,但这样可能会导致各种兼容问题,具有一定风险,在尝试之前务必备份重要文件。
Linux内核编译
下载源码
不建议通过git clone的方式从github下载Linux的源代码,文件很大,可能因为网络问题而失败,可以从一下网站下载自己需要的版本:
我选择的6.2版本,可执行如下命令:
1 | wget https://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/v6.x/linux-6.2.tar.gz |
安装编译所需模块
1 | sudo apt-get install bison flex qemu bc build-essential gcc g++ libelf-dev libssl-dev |
另外注意,在之后的编译过程中可能会出现问题,例如can’t inlcude xxx,这个时候查找对应报错并且install对应的库即可
编译
下载成功后解压,进入目录:
1 | cd linux-6.2 |
开始编译
1 | sudo make -j16 |
其中在第三步,可能会出现报错:
1 | update-initramfs: Generating /boot/initrd.img-6.2 |
原因是用来安装的boot目录没空间了,但是我们查看之后会发现空间依然充足,这其实编译过程中引入了大量不必要的内容,经过查找,可以使用如下命令:
1 | sudo make INSTALL_MOD_STRIP=1 modules_install -j4 |
接下来需要安装内核到对应目录
1 | sudo make install -j16 |
验证安装
1 | cd /boot |
应该可以看到新安装的内核版本号相关的文件
切换版本
通过命令查看当前Linux内核版本
1 | uname -r |
首先使用命令查找新内核,更新grub文件
1 | sudo update grub |
cd
到/boot/grub
修改grub.cfg
修改原文件:注释 set timeout_style = hidden, 修改timeout的值为10
重启机器,就会自动弹出选择Linux内核的界面了。
需要注意的是,如果修改的是服务器的配置,重启时由于grub界面会出现在内核加载之前,我们是无法通过ssh连接到服务器进行选择的,不过根据我的经验会自动选择一个版本,且为最新的(未进行过实验)。
通过QEMU来启动编译好的Kernel
以上我们演示了如何在本机上切换kernel版本,但如果我们只是想研究kernel的某个性质则不需要如此大费周折,QEMU为我们提供了系统虚拟化的机制。
另外,之前所述的所有部署流程均可以在容器中进行,这样做的好处是
- host无需安装大量的依赖,例如qemu
- 编译过程中出现不可逆损伤后可以快速remake
我们接下来的讨论是基于之前的操作均在容器中进行的来展开讨论,至于容器镜像的选择,使用ubuntu即可。
但需要注意的是,容器启动时必须器授予特权,否则后续的mount将无法进行
1 | docker run -it --privileged=true ubuntu:latest bash |
安装qemu
1 | sudo apt-get install qemu |
开始模拟
1 | qemu-system-x86_64 -m 512M -smp 4 -kernel ./bzImage |
很快直接失败,出现了图形化界面使用错误,这里可以尝试在qemu指令后加上--curses
在启动编译后的压缩内核时,出现无法找到文件系统的错误:
为此,需要创建磁盘镜像,制作根文件系统,且准备init程序才能启动编译后的内核,简单的做法是基于busybox构建启动程序。
编译Busybox
下载busybox压缩包之后解压,进入目录,执行以下命令:
1 | make defconfig |
在memuconfig编译完成后会进入图形化界面,此时选择
1 | Build BusyBox as a static binary (no shared libs) |
从而将Busybox编译为静态文件,编译完成并安装后,查看<path_to_disk_img_mount_point>目录,可以看到多了很多文件,此外,还需要创建额外的文件,包括rcS,inittab,proc,sys,dev等,具体可以参考博客。
以下是直接可用的脚本,需要修改相应的路径。
1 |
|
最后,在docker容器中的ubuntu就可以启动qemu了。
1 | qemu-system-x86_64 -curses -m 512M -smp 2 -kernel bzImage -drive format=raw,file=disk.raw -append "init=/linuxrc root=/dev/sda" |
If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !