2. 嵌入式Linux基础

嵌入式Linux并不是“把桌面Linux缩小”,而是一套围绕资源受限硬件重新裁剪、配置和集成的系统。理解它的第一步,是看清一个嵌入式设备从硬件到应用之间到底由哪些层次组成,以及每一层由谁负责、通过什么接口衔接。

一、嵌入式系统的四层组成

典型的嵌入式Linux系统可以划分为硬件层、引导层、内核层和根文件系统/应用层。硬件层提供CPU、内存、存储和外设;引导层(BootROM、SPL、U-Boot)负责上电后初始化DDR、加载内核;内核层负责进程调度、内存管理、驱动和设备抽象;根文件系统与用户态应用则提供Shell、库、服务和业务程序。四层之间通过明确的接口衔接:引导层把控制权交给内核,内核通过驱动访问硬件,用户态通过系统调用和/dev、/sys、/proc等接口使用内核能力。

嵌入式Linux系统组成与启动链路 用户态应用层 业务程序 / BusyBox / 系统服务 / 动态库 / 配置文件 系统调用 根文件系统 /bin /lib /etc /dev /proc /sys /usr 等目录结构 挂载 Linux内核 进程调度 / 内存管理 / 网络协议栈 / 设备驱动 / VFS 驱动访问 引导层 BootROM → SPL → U-Boot → 加载内核与设备树 上电启动 硬件层 SoC / DDR / eMMC / NAND / 串口 / 网口 / GPIO / I2C / SPI

二、Linux内核在嵌入式场景中的特点

Linux内核之所以能成为嵌入式主流选择,核心在于“可裁剪、可配置、可移植”。与通用发行版不同,嵌入式内核通常只保留目标板需要的驱动和子系统,去掉不需要的模块,以减小体积、缩短启动时间。内核提供的主要能力包括:

  • 进程与线程调度:支持实时补丁(PREEMPT_RT)后可用于工业控制等对延迟敏感的场景。
  • 内存管理:支持MMU、虚拟内存、内存映射,也支持无MMU的uClinux变体。
  • 设备驱动框架:字符设备、块设备、网络设备、平台设备、设备树(Device Tree)统一描述硬件。
  • 文件系统与VFS:支持ext4、YAFFS2、UBIFS、JFFS2、squashfs、overlayfs等,适配NOR/NAND/eMMC。
  • 网络协议栈:完整TCP/IP、Netfilter、无线、蓝牙等,便于物联网设备接入。
设备树(.dts/.dtsi)把“板级硬件差异”从内核源码中剥离出来,同一内核镜像可通过不同dtb适配多块板卡,这是嵌入式Linux工程化的重要基础。

三、交叉编译:在PC上生成目标板可执行文件

嵌入式设备通常没有足够的算力和存储来本地编译,因此采用交叉编译:在x86_64主机上使用交叉工具链,生成ARM、AArch64、MIPS等目标架构的二进制。关键概念包括:

  • 三元组:如arm-linux-gnueabihf、aarch64-linux-gnu,表示架构-厂商-系统-ABI。
  • sysroot:目标平台的头文件和库集合,编译时通过--sysroot指定。
  • 动态链接器:目标板的/lib/ld-linux-armhf.so.3必须与工具链匹配。
  • 静态与动态:调试阶段可用静态链接减少依赖,量产时常用动态链接节省空间。
# 交叉编译一个简单程序
arm-linux-gnueabihf-gcc hello.c -o hello --sysroot=/opt/sysroot
file hello
# 输出:ELF 32-bit LSB executable, ARM, EABI5 ...

# 查看动态依赖
arm-linux-gnueabihf-readelf -d hello | grep NEEDED

四、典型硬件平台与开发流程

常见嵌入式Linux硬件平台包括:树莓派(BCM2711,AArch64)、i.MX6ULL/i.MX8(NXP,工业常用)、全志H3/H616(国产SoC)、STM32MP1(Cortex-A7 + M4异构)、瑞芯微RK3399/RK3568等。它们通常具备UART调试口、SD/eMMC启动、以太网、USB和丰富GPIO。

阶段 主要任务 常用工具/命令 产出物
环境搭建 安装交叉工具链、配置串口 gcc-arm-linux-gnueabihf、minicom 可编译的主机环境
引导移植 配置DDR、时钟、启动介质 U-Boot、SPL、mkimage u-boot.bin、SPL
内核配置 选驱动、裁剪模块、配设备树 make menuconfig、dtc zImage、dtb
根文件系统 构建BusyBox、库、启动脚本 Buildroot、Yocto、busybox rootfs.tar / ext4镜像
烧录调试 下载镜像、串口登录、验证外设 dd、fastboot、tftp、nfs 可运行的目标系统

五、常见误区与复盘

误区1:用桌面gcc编译后直接拷到板子上运行,出现“cannot execute binary file”或“No such file or directory”。根因是架构或动态链接器不匹配,应使用交叉工具链并检查readelf -l中的interpreter路径。

误区2:内核能启动但根文件系统挂载失败。常见原因是bootargs中的root=设备名、文件系统类型或分区号写错,需结合串口日志逐项核对。

误区3:只改设备树却忘记重新编译dtb,或U-Boot加载了旧dtb。应确认烧录的dtb时间戳与源码一致,并在启动日志中查看“Machine model”是否正确。

把“硬件—引导—内核—根文件系统—应用”这条链路串起来,再掌握交叉编译工具链的使用方法,就具备了进入后续内核裁剪、驱动开发和系统调试的基础。真正高效的嵌入式Linux工程,不是记住某块板子的操作步骤,而是理解每一层之间的接口与依赖关系,从而在换平台、换内核版本时快速定位问题。