type
status
date
slug
summary
tags
category
created days
new update day
icon
password
Created_time
Sep 25, 2025 11:14 AM
Last edited time
Dec 15, 2025 07:49 AM

前言

最近在看宋宝华的设备驱动的书,这本书是基于 4.x 版本的内核,而这个内核非常老旧了,同时书本里面的虚拟机资料链接也已经失效了,于是对应的很多例程也没有办法进行编写与测试,没有对应的交叉编译工具链以及 rootfs 在测试的时候有着诸多不便。于是就想着自己构建一个交叉编译工具链以及 rootfs 来进行测试。
通过搜索也是看到了有着对应的同学这样做,但是他的时间也是比较久的了,所以在构建的时候也是遇到了一些问题,在这里记录一下。
首先,我们需要了解一些基本概念:
  • arm 交叉编译器:在主机上编译能够在 arm 开发板上运行的代码。
  • linux 内核:linux 运行的核心代码。
  • linux 内核模块:动态可加载内核模块,执行时依赖于内核,可以看做是内核的一个拓展,包含各种驱动程序(驱动开发就主要是这一块)。
  • linux 设备树:与硬件相关,用来描述芯片平台及板级差异的。
  • 根文件系统:内核启动时挂载的第一个文件系统,用来访问各种目录和文件,与内核互相独立。
  • bootloader:开发板启动时的引导程序,一般使用 u-boot 来制作。
所以,为了在 arm 开发板上成功运行 Linux 系统,我们有如下三个方面的任务:
  1. 制作 bootloader;
  1. 编译 linux 内核、linux 内核模块、linux 设备树;
  1. 制作根文件系统。
下面,我们使用 qemu 虚拟机来上手嵌入式 linux 的开发。

1.安装 qemu 与 arm 交叉编译工具(Fedora)

1.1 安装 qemu:

若需要安装较新版本的 qemu,可以自行下载源码手动编译安装)
使用 qemu-system- 命令可以查看 qemu 支持的 CPU 架构。
使用 qemu-system-arm --version 命令可以查看 qemu 的版本。
使用 qemu-system-arm -M help 命令可以查看支持的开发板类别。

1.2 安装交叉编译工具链

因为 Fedora 默认不带有交叉编译工具链的 glibc ,所以在后面构建 busybox 的时候会出现 byteswap.h 找不到的问题,虽然有已经预编译好的交叉编译工具链,但是想着自己也是熟悉一下整个工作流程,以及可以自己定义与修改的原则,在这里选择使用 crosstool-ng 来进行自定义的交叉编译工具链的编译与配置。

1.2.1 下载安装 crosstool-ng

  1. 进入解压后的文件目录,运行 ./configure(无参数为默认配置),若提示缺少某些工具,则使用 yum/apt 安装,然后再次运行 ./configure ,直到不再提示缺少工具。
  1. 编译 Crosstool-NG :命令 make
  1. 安装 Crosstool-NG:命令 sudo make install
  1. 命令 ct-ng version,可以查看当前安装的 Crosstool-NG 版本

1.2.2 使用 crosstool-ng

  1. 随意建立一个文件夹,如 tools,编译工具链存放临时文件所用
  1. 进入tools 文件夹
  1. 命令 ct-ng list-samples 可查看 Crosstool-NG 提供的配置,依据目标芯片的架构进行选择(本文选择 arm-unknown-linux-gnueabi
  1. 命令 ct-ng arm-unknown-linux-gnueabi 选用官方的这一配置,则在当前目录下会沈城 .config 文件,可使用 ls -a 查看到是否存在此文件
  1. 命令 ct-ng menuconfig 使用 menuconfig 工具对配置文件进行编辑(本文保持默认配置,不进行编辑)
  1. 命令 ct-ng build 进行编译以及安装(默认安装路径为当前用户家目录下的 x-tools 目录,即 ~/x-tools )
  1. 实测 Debian Buster 与 Fedora下编译无误

2.Linux 内核与设备树编译

下载 Linux 内核:https://www.kernel.org/ 选择长期维护的 6.12 版本 ,点击 tarball 进行下载:
将下载下来的 Linux 内核拷贝到 home 目录,使用 tar xvf linux-4.4.232.tar.xz 进行解压缩。
解压好后输入 cd linux-6.12.48/ 进入 linux 内核目录下,配置环境变量
这里我们选择 vexpress 系列作为我们虚拟开发板,在 linux 内核目录下,输入 make vexpress_defconfig 对开发板进行配置,编译后生成.config 文件:
配置好后,编译内核,生成 zImage 镜像文件:make zImage -j6(多线程编译)
编译内核模块:make modules -j4
编译设备树,获得 dtb 文件:make dtbs
在 linux 内核目录下,使用 qemu 运行内核:qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "console=ttyAMA0",该命令指定了开发板类别、内存大小、内核 zImage 文件、dtb 文件、无图形界面、串口。
可以看到内核开始运行起来:
notion image
但是卡在了挂载根文件系统处,别急,接着往下看。

3. busybox 根文件系统制作

QEMU 提供了一组快捷键来控制虚拟机的操作。要退出 QEMU,可以按下 Ctrl+A,然后松开这两个键,接着按下 x 键。这里需要注意的是,a 和 x 都应该是小写字母,并且在按下 x 之前必须先释放 Ctrl+A。
在 QEMU 窗口中
这种方法可以优雅地终止 QEMU,而不需要在另一个终端中执行命令。
接下来,使用 busybox 制作根文件系统。 下载源码:https://busybox.net/downloads/,下载最新版本即可。
配置环境变量
解压缩:tar xvf busybox-1.32.0.tar.bz2, 进入 busybox 源码目录:cd busybox-1.32.0/
接着,输入命令 make defconfig 回车等待配置完毕。
也可以使用图形化配置 make menuconfig,按回车然后进入 Settings 选项,找到 Build Options,点 y 键将选项 Build static binary(编译成静态)选中,然后退出:
notion image
notion image
 
回到命令行,直接编译:make -j4
然后执行 make install,生成一个 _install 文件夹。 准备好后,下一步开始制作根文件系统。
输入 cd 回到 home 目录,新建目录 mkdir rootfs,进入该目录 cd rootfs/,将刚才生成的 _install 目录里的所有文件拷贝到该目录下:
新建目录 mkdir lib,将 arm 交叉编译器的库复制过来:
在 rootfs 目录下新建目录 mkdir dev/,进入该目录 cd dev/,创建节点 sudo mknod -m 666 tty1 c 4 1(这里创建了一个串口字符设备,主设备号为 4,从设备号为 1)。
重复创建多个串口设备,注意分配好从设备号:
创建一个控制台节点:mknod -m 666 console c 5 1
创建一个空节点:mknod -m 666 null c 1 3
创建好的字符设备用 ls 查看:
在 rootfs 目录下新建目录 init.d/vim init.d/rcS chmod +x init.d/rcS
回到 home 目录,输入命令 dd if=/dev/zero of=rootfs.ext4 bs=1M count=64 生成虚拟 SD 卡系统镜像,可以得到一个 rootfs.ext4 文件。
格式化该镜像:mkfs.ext4 rootfs.ext4
挂载该镜像到本地:mount rootfs.ext4 /mnt -o loop
将之前准备的 rootfs 目录下的所有文件都拷贝到该镜像挂载点:cp -r ~/rootfs/* /mnt/
卸载:umount /mnt/
进入 linux 源码目录: cd linux-6.12.48/
使用 qemu 启动内核:qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd ~/rootfs.ext4,这里比之前多指定了一个 sd 镜像。
notion image
若要图形化启动,使用命令:

4.使用 u-boot 加载 Linux 内核

下载源码:(较新版本的 u-boot 需要更高版本的 gcc 来编译,为了方便起见,可以选用较早版本的 u-boot)
待补充…

参考文献

 
瑞芯微 SDK Docker 构建镜像深度解析Linux设备树(DTS):设计原理、实现框架与实例分析
Loading...