QEMU学习之路(5)— 从0到1构建Linux系统镜像

发布于:2025-04-05 ⋅ 阅读:(13) ⋅ 点赞:(0)

QEMU学习之路(5)— 从0到1构建Linux系统镜像

一、前言

参考:从内核到可启动镜像:0到1构建你的极简Linux系统

二、linux源码获取

安装编译依赖

sudo apt install -y build-essential libncurses-dev flex bison libssl-dev libelf-dev

1、从Linux官网下载源码

wget https://www.kernel.org/pub/linux/kernel/v6.x/linux-6.14.tar.xz

下好后使用命令解压

tar xvf linux-6.14.tar.xz

2、使用git拉取

git clone --depth 1 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git -b v6.14 linux-6.14

3、国内镜像源获取

从国外的网站下载内核可能很慢,可以尝试使用国内的镜像源,例如清华大学的开源镜像站

git clone --depth 1 https://mirrors.tuna.tsinghua.edu.cn/git/linux.git -b v6.14 linux-6.14

三、内核构建

源码获取好后可以使用如下命令生成默认配置

make defconfig

然后编译内核

make -j$(nproc)

编译后得到内核镜像文件:arch/x86_64/boot/bzImage
在这里插入图片描述

四、构建initramfs

initramfs(Initial RAM File System)是 Linux 系统启动过程中使用的 临时根文件系统,它存储在内存中,用于在内核加载后、挂载真实根文件系统前完成关键初始化任务。
使用如下命令构造目录结构与设备节点

mkdir -p initramfs/{bin,dev,proc,sys}
cd initramfs
sudo mknod dev/console c 5 1
sudo mknod dev/null c 1 3
sudo chown root:root dev/{console,null}

BusyBox 是一个高度优化的 多合一 Unix 工具集,它将数百个常用 Unix 工具(如 ls、cat、grep、mount、ifconfig 等)集成到一个精简的二进制文件中。
下载BusyBox 源码:

wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2

解压

tar -xf busybox-1.36.1.tar.bz2

进入源码目录进行配置

cd busybox-1.36.1
make menuconfig

进入配置界面后,启用以下选项吗,选择静态方式编译busybox,目的是将程序的所有依赖库直接打包进二进制文件,避免了Linux系统运行时依赖动态库。

Settings  --->
    [*] Build static binary (no shared libs) 

编译busybox

make -j$(nproc)

然后部署到initramfs

make install CONFIG_PREFIX=../work/initramfs

在initramfs目录新建init文件,它作为Linux 启动镜像(initramfs)中的 首个用户态进程(PID 1),由内核直接启动,承担着从内核过渡到用户空间的关键桥梁作用,主要任务是为后续系统启动准备必要的运行环境。输入内容如下:

#!/bin/sh
/bin/echo "Hello Linux"
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs devtmpfs /dev

exec /bin/sh

使用chmod +x init命令添加可执行权限
在这里插入图片描述
然后将其打包到initramfs.img镜像文件中。

find . | cpio -H newc -o | gzip > ../initramfs.img

使用如下命令检查打包结果

file ../initramfs.img 

在这里插入图片描述

五、启动测试

将bzImage拷贝到当前目录
在这里插入图片描述
使用如下命令测试启动

qemu-system-x86_64 -kernel bzImage -initrd initramfs.img

启动后显示界面如下:
在这里插入图片描述
也可使用如下命令不带图形界面启动

qemu-system-x86_64 -kernel bzImage -initrd initramfs.img -m 1G -nographic -append "earlyprintk=serial,ttyS0 console=ttyS0"

六、制作ISO镜像

ISO文件是一种标准的光盘镜像格式(遵循ISO 9660文件系统规范),通常用于封装完整的可启动操作系统或软件集合。在Linux系统构建中,ISO文件的核心作用是将内核(vmlinuz)、初始内存盘(initramfs.img)和引导程序(如GRUB)等关键组件打包成一个可物理刻录(光盘/USB)或虚拟机加载的独立镜像。

构建boot目录

mkdir -p iso/boot/grub

将前面编译或者构建好的内核镜像文件(bzImage或者Image.gz)、根文件系统镜像文件(initramfs.img)添加到boot目录中

cp ../linux-6.14/arch/x86_64/boot/bzImage iso/boot/vmlinuz
cp ./initramfs.img iso/boot/initramfs.img

新建GRUB配置文件

touch iso/boot/grub/grub.cfg

输入内容如下

menuentry "Custom Linux" {
    linux /boot/vmlinuz root=/dev/ram0 rw
    initrd iso/boot/initramfs.img
}

在这里插入图片描述

安装工具依赖包

sudo apt install mtools xorriso

生成ISO

grub-mkrescue -o custom-linux.iso iso/

验证ISO结构

xorriso -indev custom-linux.iso -ls

在这里插入图片描述
使用如下命令启动:

qemu-system-x86_64 -cdrom custom-linux.iso

七、开发驱动

创建hello.c文件,内容如下所示:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("william");
MODULE_DESCRIPTION("Hello module");
MODULE_VERSION("0.1");


static int __init hello_init(void)
{
	printk(KERN_INFO "Loading hello module\n");
	printk(KERN_INFO "hello world\n");
	return 0;
}


static void __exit hello_exit(void)
{
	printk(KERN_INFO "exit module\n");
}

module_init(hello_init);
module_exit(hello_exit);

编写Makefile如下所示:

KERNELDIR=/home/william/project/linux/linux-6.14

obj-m := hello.o

all:
	make -C ${KERNELDIR} M=${PWD} modules

clean:
	make -C ${KERNELDIR} M=${PWD} clean

.PHONY: all clean

编译后将hello.ko拷贝到initramfs/usr/文件夹下,重新生成initramfs.img后启动系统
在这里插入图片描述
进入/usr目录后加载驱动,卸载驱动,可看到如下打印
在这里插入图片描述