1. Linux内核开发环境搭建

嵌入式Linux内核驱动开发的第一步,是构建一个稳定、可复现的开发环境。本章将指导你从零开始搭建虚拟机、配置内核源码树、安装交叉编译工具链,并建立NFS与TFTP调试环境。这套环境将贯穿整个课程,支撑后续所有驱动实验。

环境概览:主机使用Windows/macOS,虚拟机运行Ubuntu 22.04 LTS作为开发工作站,目标板为ARM Cortex-A系列(如QEMU模拟的vexpress-a9或真实开发板)。所有工具链和调试服务均部署在虚拟机中。

1.1 虚拟机安装Ubuntu

推荐使用VMware Workstation Pro 17+或VirtualBox 7+。以下步骤以VMware为例:

  1. 下载Ubuntu Server 22.04 LTS ISO(建议使用Server版,减少桌面环境资源占用)。
  2. 创建虚拟机:分配4核CPU、8GB内存、80GB磁盘(动态扩展)。
  3. 网络配置:使用桥接模式,确保虚拟机与主机在同一网段,便于后续NFS/TFTP通信。
  4. 安装系统:选择最小化安装,仅安装OpenSSH Server和标准系统工具。
  5. 更新与基础包:
sudo apt update && sudo apt upgrade -y
sudo apt install -y build-essential git vim net-tools nfs-kernel-server tftpd-hpa
关键配置:固定虚拟机IP地址(例如192.168.1.100),避免每次重启后IP变化导致调试中断。编辑 /etc/netplan/00-installer-config.yaml 设置静态IP。
嵌入式Linux开发环境拓扑 主机 Windows/macOS SSH客户端 / IDE Ubuntu 22.04 虚拟机 内核源码树 交叉编译工具链 NFS / TFTP 服务 目标板 ARM Cortex-A QEMU / 真实硬件 SSH / SCP NFS/TFTP 工作流程 ① 主机通过SSH连接虚拟机,编写驱动代码 ② 虚拟机交叉编译驱动 → ③ 通过NFS/TFTP部署到目标板 → ④ 目标板加载驱动并测试

1.2 配置内核源码树

内核源码树是驱动开发的核心依赖。你需要下载与目标板匹配的内核版本,并完成首次编译。

步骤 命令/操作 说明
1. 下载内核 wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.80.tar.xz 选择LTS版本,稳定性优先
2. 解压 tar -xf linux-6.1.80.tar.xz -C ~/ 解压到用户目录
3. 配置内核 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- vexpress_defconfig 使用vexpress默认配置
4. 编译内核 make -j$(nproc) ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage 生成压缩内核镜像
5. 编译设备树 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs 生成.dtb文件
6. 编译模块 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules 编译内核模块
常见错误:如果编译时提示缺少ncurses库,执行 sudo apt install libncurses-dev。如果使用menuconfig图形配置,需要安装 libncurses5-dev。
内核源码树编译流程 下载源码 配置内核 编译内核 生成镜像 编译输出产物 zImage (内核镜像) *.dtb (设备树) *.ko (内核模块)

1.3 安装交叉编译工具链

交叉编译工具链允许你在x86主机上编译出ARM架构的可执行文件。推荐使用Linaro提供的GCC工具链。

# 下载ARM GCC工具链
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/

# 添加环境变量
echo 'export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin' >> ~/.bashrc
source ~/.bashrc

# 验证安装
arm-linux-gnueabihf-gcc --version
工具链组件 用途 示例命令
arm-linux-gnueabihf-gcc C语言交叉编译器 编译内核、驱动、应用程序
arm-linux-gnueabihf-ld 链接器 链接目标文件生成可执行文件
arm-linux-gnueabihf-objdump 反汇编工具 查看二进制文件指令
arm-linux-gnueabihf-objcopy 格式转换工具 ELF转二进制/十六进制
选择建议:对于Linux 6.x内核,推荐使用GCC 10+工具链。如果目标板是Cortex-A7/A15,使用 arm-linux-gnueabihf- 前缀;如果是Cortex-A53/A72(64位),使用 aarch64-linux-gnu- 前缀。

1.4 搭建NFS与TFTP调试环境

NFS(网络文件系统)允许目标板挂载虚拟机的文件系统,实现内核模块的热替换调试。TFTP(简单文件传输协议)用于快速下载内核镜像和设备树到目标板。

1.4.1 NFS服务配置

# 安装NFS服务器
sudo apt install nfs-kernel-server

# 创建共享目录
sudo mkdir -p /srv/nfs/rootfs
sudo chown nobody:nogroup /srv/nfs/rootfs
sudo chmod 777 /srv/nfs/rootfs

# 配置导出文件
echo "/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports

# 重启服务
sudo systemctl restart nfs-kernel-server
sudo exportfs -a

1.4.2 TFTP服务配置

# 安装TFTP服务器
sudo apt install tftpd-hpa

# 配置TFTP目录
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp

# 修改配置文件 /etc/default/tftpd-hpa
# 内容如下:
# TFTP_USERNAME="tftp"
# TFTP_DIRECTORY="/srv/tftp"
# TFTP_ADDRESS="0.0.0.0:69"
# TFTP_OPTIONS="--secure --create"

# 重启服务
sudo systemctl restart tftpd-hpa
NFS + TFTP 调试架构 Ubuntu 虚拟机 NFS Server TFTP Server 共享目录 /srv/nfs /srv/tftp 目标板 (ARM) U-Boot Bootloader Linux Kernel 挂载NFS根文件系统 TFTP: 下载zImage/dtb NFS: 挂载根文件系统

1.4.3 目标板启动参数配置

在U-Boot中设置以下环境变量,实现从NFS启动:

setenv ipaddr 192.168.1.101
setenv serverip 192.168.1.100
setenv netmask 255.255.255.0
setenv gatewayip 192.168.1.1

# 通过TFTP下载内核和设备树
setenv bootcmd 'tftp 0x60000000 zImage; tftp 0x65000000 vexpress-v2p-ca9.dtb; bootz 0x60000000 - 0x65000000'

# 通过NFS挂载根文件系统
setenv bootargs 'console=ttyAMA0,115200 root=/dev/nfs nfsroot=192.168.1.100:/srv/nfs/rootfs rw ip=192.168.1.101'

saveenv
boot
调试效率提升:将编译好的内核模块(.ko文件)直接复制到NFS共享目录的对应路径下,目标板启动后即可通过 insmod / rmmod 动态加载/卸载驱动,无需重启系统。这是驱动开发中最常用的调试循环。

1.5 环境验证清单

完成上述配置后,使用以下清单验证环境是否就绪:

验证项 验证方法 预期结果
虚拟机网络 ping 192.168.1.1 能够ping通网关
交叉编译工具链 arm-linux-gnueabihf-gcc --version 显示版本信息
内核编译 ls -lh arch/arm/boot/zImage 文件存在且大小正常
NFS服务 showmount -e localhost 显示共享目录列表
TFTP服务 tftp localhost -c get test.txt 成功下载文件
目标板启动 串口输出日志 内核启动完成,进入shell
防火墙注意:如果目标板无法连接NFS/TFTP,检查虚拟机防火墙是否放行相关端口:NFS使用2049端口,TFTP使用69端口(UDP)。执行 sudo ufw allow 2049 和 sudo ufw allow 69/udp。