当前位置:首页>Linux>不用开发板,玩一下自己的嵌入式Linux系统

不用开发板,玩一下自己的嵌入式Linux系统

  • 2026-10-11 06:55:57
不用开发板,玩一下自己的嵌入式Linux系统

大家好,我是写代码的篮球球痴。

做嵌入式 Linux 开发最烦人的事是什么?

烧 SD 卡。插板子。等启动。看串口。挂了。拔电源。重烧。

上一篇文章写了 busybox,已经有了最小的根文件系统,那我们是不是就可以构建自己的嵌入式 Linux 系统了?

所以这篇文章就来了,用 QUME 搭建自己的嵌入式 Linux 系统,让我们对 Linux 更加贴切的认识。。。。。

嵌入式开发:真机 SD 卡迭代 vs QEMU 30 秒循环

用 QEMU 模拟的话:

改一行代码 → make → 启动虚拟机 → 看 dmesg,30 秒。5 分钟够你试 10 次。

这不是「替代真机测试」——QEMU 没有 SPI Flash,没有 I2C 传感器,没有 DMA。它解决的是真机开发中那 80% 的「能不能编译过」「能不能加载」「会不会 panic」的快速验证。剩下 20% 硬件相关的 bug,你还是要买板子来测试实验。

精髓是——QEMU 让你在办公室就把内核玩烂了再上真机。


整个环境不到 50MB。一个 Linux 内核,一个 Busybox 根文件系统,一个 QEMU 虚拟机。从零到能跑,15 分钟。

三个零件——这是 Linux 初学者到进阶的核心,这也是理解 Linux 的核心,我们所有谈论的 Linux 就不应该只谈论 Linux 内核,因为它只是 Linux 系统的一部分。

嵌入式 Linux 的三个零件:Linux Kernel + Busybox + initramfs

内核(大脑):

wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.40.tar.xztar -xf linux-6.12.40.tar.xz && cd linux-6.12.40make x86_64_defconfigmake -j$(nproc)

输出 `arch/x86/boot/bzImage`,压缩后约 12MB,QEMU 直接用。

`x86_64_defconfig` 这个配置值得说一句——它是内核自带的「能跑就行」配置,包含了 Virtio 驱动(QEMU 的虚拟磁盘/网络)、ext4 文件系统、PCI 总线支持,刚好够在 QEMU 里启动到 shell。你要做 ARM 开发,换 `ARCH=arm64 make defconfig`,一样流程。做 RISC-V 也一样。

Busybox(工具集):

嵌入式 Linux 的瑞士军刀——一个不到 2MB 的二进制,提供了 ls、cp、mount、ifconfig、vi、wget 等 300 多个常用命令。

wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2tar -xf busybox-1.36.1.tar.bz2 && cd busybox-1.36.1make defconfigsed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .configmake -j$(nproc)make install

静态编译这里有一个坑,我当年卡了一整个下午。

如果你的 Busybox 是动态链接的,在 initramfs 里启动后 `/bin/sh` 会提示 `not found`——不是 sh 不存在,是动态链接器 `ld-linux.so` 不在 initramfs 里。错误信息极其误导人,你盯着文件看了半天,文件明明在,权限也对,它就是起不来。

所以一定记得 `CONFIG_STATIC=y`,或者把动态库手动拷进 initramfs。

initramfs(根文件系统):

内核启动后第一个挂载的文件系统。目录结构长这样:

/tmp/initramfs/├── bin/│   ├── busybox│   └── sh -> busybox├── sbin/│   └── init├── etc/├── proc/├── sys/└── dev/

最关键的 `init` 脚本:

#!/bin/shmount -t proc proc /procmount -t sysfs sysfs /sysmount -t devtmpfs devtmpfs /devecho "=== Embedded Linux Ready ==="echo "Kernel: $(uname -r)"echo "Free memory: $(free -m | awk 'NR==2{print $4}') MB"exec /bin/sh

打包:

cd /tmp/initramfsfind . -print0 | cpio --null -ov --format=newc | gzip -9 > ~/initramfs.cpio.gz

最终产物 `initramfs.cpio.gz`,大约 1-2MB。


东西齐了,一行命令启动:

qemu-system-x86_64 \    -kernel ~/linux-6.12.40/arch/x86/boot/bzImage \    -initrd ~/initramfs.cpio.gz \    -append "console=ttyS0 nokaslr quiet" \    -nographic \    -m 256M \    -smp 2

`-kernel` 直接加载内核,跳过 BIOS/UEFI 引导,省 2-3 秒。

`-initrd` 把 initramfs 加载到内存。

`-append "console=ttyS0"` 让内核日志输出到串口,`-nographic` 模式下显示在你的终端里。`nokaslr` 关掉内核地址随机化——调试时需要固定地址,不然断点打不上。`-m 256M` 分 256MB 内存,内核对 Busybox 绰绰有余。`-smp 2` 给两个 CPU 核心,你能在上头测试 SMP 内核模块。

3 秒开始滚屏。然后:

QEMU 启动到 Ready:内核日志 + Busybox shell prompt
=== Embedded Linux Ready ===Kernel: 6.12.40Free memory: 232 MB/ #

到这里,你有了一个完整的、可调试的 Linux 环境。写内核模块、改调度器、测试 eBPF 程序,全在这个沙箱里。


真正有价值的是 GDB 直接连 QEMU。

真机调试内核得用 JTAG 调试器,断点经常不稳,一套下来几千块。QEMU 内置 GDB server,零成本:

qemu-system-x86_64 -kernel bzImage -initrd initramfs.cpio.gz \    -append "console=ttyS0 nokaslr" -nographic -m 256M -s -S

另一个终端:

$ gdb vmlinux(gdb) target remote :1234(gdb) break start_kernel(gdb) continue

你可以在内核启动过程中下断点,单步跟踪你自己的内核模块,看内存和寄存器状态,测试 oops/panic 时的调用栈回溯。用这套东西学内核源码,效率是「读代码然后猜行为」的十倍以上。


写一个 hello world 内核模块,真机和 QEMU 的差距有多大?

真机流程:写代码 → 交叉编译 → 复制到 SD 卡(或 NFS)→ 插卡上电 → 等启动 → insmod → panic,板子挂了 → 拔电源 → 从头来。

QEMU 流程:写代码 → make → insmod → panic → Ctrl+C → 修复 → 重启,2 秒。

这是一种根本性的心理变化。

在真机上你不敢写冒险的代码——挂一次成本太高,重新烧卡接串口打开终端,心态已经崩了。在 QEMU 里挂就挂了,代码还在编辑器里,改完 20 秒后又是全新内核。

make -C ~/linux-6.12.40 M=$PWD modulesinsmod my_driver.kodmesg | tail -5

这种「你敢写、敢改、敢试」的节奏,是内核开发学习曲线最陡那段最好的缓冲。


换 ARM 或者 RISC-V,改两行:

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfigmake ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)qemu-system-aarch64 -M virt -cpu cortex-a53 -kernel Image -initrd initramfs.cpio.gz \    -append "console=ttyAMA0" -nographic -m 256Mmake ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfigqemu-system-riscv64 -M virt -kernel Image -initrd initramfs.cpio.gz \    -append "console=ttyS0" -nographic -m 256M

`-M virt` 是 QEMU 的虚拟平台,没有真实硬件对应,但包含了 ARM/RISC-V 架构的通用外设(PCIe、virtio-blk、PL011 串口)。适合软件验证,不适合硬件驱动开发。


说实话,QEMU 不是万能的。

硬件外设不存在。QEMU 不会模拟你的 SPI Flash、I2C 传感器、CAN 控制器。如果你的内核模块是操作具体硬件的,最终还是要上真机。这不是 QEMU 的缺陷,是虚拟化本身的边界。

时序不可信。QEMU 的指令执行时间是模拟的,中断延迟、DMA 传输时间跟真实硬件没有可比性。依赖精确定时的代码——比如用 `ndelay()` 做时序控制——在 QEMU 能跑不代表真机能跑。

内存模型简化。QEMU 默认平坦内存模型。如果你的代码涉及 cache coherency、内存屏障、DMA 缓存一致性——这些在 QEMU 里都不会暴露。必须上真机。

Buildroot 是更完整的替代方案。如果你需要的不只是内核加 shell,还要 Qt、OpenSSL、Python、蓝牙协议栈,手动编译不是好主意。

git clone git://git.busybox.net/buildrootcd buildrootmake qemu_x86_64_defconfigmake -j$(nproc)./output/images/start-qemu.sh

Buildroot 帮你管了工具链、库依赖、文件系统打包。代价是 build 一次 30 分钟,失去手写 init 脚本的透明度。两个都得会——开发实验阶段用手工环境,验证完整功能切到 Buildroot。


嵌入式 Linux 开发环境搭建,说到底就是「快速失败」的问题。

你把「改一行代码到看到结果」从 5 分钟压到 30 秒,就能多试 10 种方案。多试的 10 次里,至少有一次能让你少烧一张 SD 卡。

今天的脚本,明天就能出第一个内核模块。

END

来源:嵌入式Linux


版权归原作者所有,如有侵权,请联系删除。
▍推荐阅读
嵌入式专用的AI代码审查Checklist
海思、瑞芯微、全志……说说这几家芯片的使用感受
梅赛德斯-奔驰把汽车开发板开源了!STM32G4+扩展板+Zephyr,全套PCB 3D模型,这配置有点香
→点关注,不迷路←

最新文章

随机文章