当前位置: 首页 > news >正文

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

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目录后加载驱动,卸载驱动,可看到如下打印
在这里插入图片描述

http://www.dtcms.com/a/111520.html

相关文章:

  • 【学习篇】fastapi接口定义学习
  • 19.TCP相关实验
  • 哈密尔顿路径(Hamiltonian Path)及相关算法题目
  • 前端快速入门学习3——CSS介绍与选择器
  • 第三季:挪威
  • 阿里Qwen 创建智能体,并实现ubantu系统中调用
  • 对用户登录设计测试用例
  • Transformer由入门到精通(一):基础知识
  • CSS快速上手
  • BUUCTF-web刷题篇(10)
  • 封装自己的api签名sdk
  • 数据结构 -- 图的存储
  • SpringBoot定时任务深度优化指南
  • ubuntu部署ollama+deepseek+open-webui
  • OpenCV 实现对形似宝马标的黄黑四象限标定位
  • 字符串移位包含问题
  • CExercise_1_4continue关键字在while循环和for循环中,实现的功能有什么区别?
  • Neo4j操作数据库(Cypher语法)
  • NO.61十六届蓝桥杯备战|基础算法-双指针|唯一的雪花|逛画展|字符串|丢手绢(C++)
  • 管理系统 UI 设计:提升企业办公效率的关键
  • (多看) CExercise_05_1函数_1.2计算base的exponent次幂
  • 花卉识别分类系统,Python/resnet18/pytorch
  • MySQL简介
  • 大钲资本押注儒拉玛特全球业务,累计交付超2500条自动化生产线儒拉玛特有望重整雄风,我以为它破产倒闭了,担心很多非标兄弟们失业
  • SpringBoot配置文件多环境开发
  • 空中无人机等动态目标识别2025.4.4
  • Nacos注册中心AP模式核心源码分析(单机模式)
  • 前端知识点---本地存储(javascript)
  • IObit Uninstaller:深度清理残留文件
  • 黑马点评_知识点