1. 课程导学与实验环境搭建
嵌入式Linux内核开发,说白了就是给硬件穿上操作系统这件"衣服"。我做了十几年内核开发,见过太多人一上来就啃源码,结果被编译环境折腾得半途而废。所以这一章,我们先搭好台子,再唱戏。
1.1 嵌入式Linux内核开发全景图
先看看我们要学什么,整个知识体系长什么样。
这张图我画了很多次。每次带新人,我都会先让他们看这个框架。内核开发不是零散的知识点,而是一整套工程方法。
1.2 课程目标与学习方法
这门课要解决什么问题?说白了就三个:
- 能定制 —— 根据硬件裁剪内核,去掉不需要的功能
- 能调试 —— 驱动出问题了,知道怎么定位
- 能排障 —— 系统崩溃了,能快速找到根因
我个人的学习建议是:别只看,要动手。每章我都会给实验,你跟着敲一遍,比看十遍书都管用。
学习节奏建议
- 前5章:打好环境基础,别跳步
- 中间15章:跟着实验走,每章至少跑通一个例子
- 后10章:综合实战,尝试自己复现故障场景
1.3 Ubuntu虚拟机与交叉编译工具链安装
先搞定开发机。我推荐用 Ubuntu 22.04 LTS,64位版本。为什么?因为社区支持最好,遇到问题搜一下就有答案。
1.3.1 虚拟机安装要点
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| CPU核心数 | 4核以上 | 编译内核时多核并行能省大量时间 |
| 内存 | 8GB以上 | 低于4GB编译大型内核会卡死 |
| 磁盘 | 80GB以上 | 内核源码+编译产物很占空间 |
| 网络 | 桥接模式 | 方便后续与开发板通信 |
注意:磁盘空间别省。我见过有人只分40GB,编译到一半报磁盘满,还得重新扩容,浪费时间。
1.3.2 交叉编译工具链安装
交叉编译,就是在x86电脑上编译出ARM能跑的程序。工具链我推荐用 Linaro 的 gcc-arm-linux-gnueabihf。
# 安装依赖
sudo apt update
sudo apt install -y build-essential git vim
# 下载交叉编译工具链
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
# 解压到 /opt
sudo tar -xf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt
# 配置环境变量(写入 ~/.bashrc)
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin
# 验证安装
arm-linux-gnueabihf-gcc --version
验证成功会看到版本号。嗯,这里要注意:路径别写错,我刚开始学的时候经常把路径拼错,然后报"command not found",排查半天才发现是少了个斜杠。
1.4 QEMU模拟器与ARM开发板环境搭建
没有开发板怎么办?用QEMU模拟。有板子怎么办?直接烧录。两种方式我都讲。
1.4.1 QEMU模拟ARM环境
QEMU可以模拟ARM的vexpress-a9开发板。我习惯用这个板型,因为Linux内核主线对它支持最好。
# 安装QEMU
sudo apt install -y qemu-system-arm
# 下载内核与文件系统(以4.19内核为例)
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.xz
tar -xf linux-4.19.tar.xz
# 配置内核(vexpress_defconfig)
cd linux-4.19
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- vexpress_defconfig
# 编译内核
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4
# 启动QEMU
qemu-system-arm \
-M vexpress-a9 \
-kernel arch/arm/boot/zImage \
-dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
-append "console=ttyAMA0" \
-nographic
关键点:
-M指定机器类型,vexpress-a9 是最常用的-kernel指定内核镜像,就是编译出来的 zImage-dtb指定设备树,描述硬件信息-nographic用终端模拟串口,不用图形界面
启动后你会看到内核启动日志,最后停在 VFS: Cannot open root device。别慌,这是正常的——我们还没挂载根文件系统。后面章节会教你怎么制作根文件系统。
1.4.2 真实ARM开发板环境
如果你有开发板,比如树莓派或友善之臂的板子,流程类似:
- 在Ubuntu上交叉编译内核
- 将zImage和设备树文件拷贝到SD卡
- 设置开发板从SD卡启动
- 通过串口或SSH登录调试
| 开发板 | 内核配置 | 启动方式 |
|---|---|---|
| 树莓派3B+ | bcm2837_defconfig | SD卡 + config.txt |
| 友善之臂NanoPi | nanopi_defconfig | SD卡 + boot.scr |
| QEMU vexpress | vexpress_defconfig | 命令行直接启动 |
我的建议:刚开始用QEMU就够了。等把内核编译、驱动加载这些流程跑熟了,再上真实板子。不然板子坏了、线接错了,排查起来很痛苦。我曾经烧录时把SD卡分区表搞坏了,折腾了一下午才恢复。
1.5 环境验证
环境搭好了,怎么确认没问题?跑一个最简单的内核模块试试。
// hello.c
#include <linux/module.h>
#include <linux/kernel.h>
static int __init hello_init(void)
{
printk(KERN_INFO "Hello, Embedded Linux!\n");
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "Goodbye!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
# Makefile
obj-m := hello.o
all:
make -C /path/to/linux-4.19 M=$(PWD) ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
clean:
make -C /path/to/linux-4.19 M=$(PWD) ARCH=arm clean
编译通过后,把 hello.ko 放到QEMU的文件系统里,用 insmod hello.ko 加载。如果看到 Hello, Embedded Linux! 打印出来,恭喜你,环境全部就绪。
常见坑:
- 内核版本与工具链不匹配 —— 用4.19内核配7.5工具链没问题
- Makefile里的路径写错 —— 用绝对路径最保险
- 模块编译出来是x86格式 —— 检查CROSS_COMPILE是否生效