Linux基础与环境搭建:发行版选择、交叉编译工具链安装、TFTP/NFS服务配置

嵌入式开发的第一步,说白了就是搭环境。很多人觉得这事简单,不就是装个系统嘛。但我见过太多项目在环境上栽跟头——工具链版本不对、文件系统挂不上、调试半天发现是网络服务没配好。嗯,咱们这一章就把这些基础打扎实。

2.1 Linux发行版怎么选?

做嵌入式开发,我个人的习惯是优先选 Ubuntu LTS 或 Debian。为什么?社区活跃、包管理成熟、遇到问题搜一下就有答案。

发行版 适用场景 我的建议
Ubuntu 20.04/22.04 LTS 通用嵌入式开发、ARM平台 新手首选,资料最多
Debian 11/12 服务器、长期稳定项目 比Ubuntu更稳,但包略旧
Fedora 尝鲜、RHEL系开发 内核新,但社区支持弱一些
Arch Linux 极简、定制化需求 不推荐新手,滚动更新容易出问题
我的经验:如果你用的是国产芯片(全志、瑞芯微、海思),厂商SDK通常基于Ubuntu 18.04或20.04验证。别盲目追新,跟厂商对齐能省很多麻烦。

2.2 交叉编译工具链安装

交叉编译,说白了就是在PC上编译出能在ARM板子上跑的程序。你想想看,板子那么弱,跑个gcc都费劲,怎么可能在上面编译大项目?

2.2.1 工具链的选择

我遇到过三种情况:

  • 官方预编译包:ARM官网的gcc-arm-none-eabi,适合裸机或RTOS
  • 芯片厂商提供:比如NXP的Linaro GCC、TI的CGT
  • 自己用crosstool-NG编译:适合特殊架构或定制需求

我个人最常用的是 Linaro GCC,稳定、更新及时。安装步骤很简单:

# 下载ARM 32位工具链
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

# 解压到指定目录
tar -xvf 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
避坑指南:我曾经在64位系统上装了32位工具链,结果死活跑不起来。后来发现缺了32位库:sudo apt install lib32z1 lib32ncurses5。嗯,这个坑我替你们踩过了。

2.2.2 工具链命名规则

你可能会看到一堆名字:arm-linux-gnueabihf、aarch64-linux-gnu、arm-none-eabi……它们到底啥区别?

前缀 架构 操作系统 ABI 典型用途
arm-linux-gnueabihf ARM 32位 Linux 硬浮点 树莓派、全志H3
aarch64-linux-gnu ARM 64位 Linux 标准 树莓派4B、RK3399
arm-none-eabi ARM 32位 无OS 嵌入式ABI STM32裸机、FreeRTOS
arm-linux-androideabi ARM 32位 Android 嵌入式ABI Android NDK开发

2.3 TFTP服务配置

TFTP这玩意儿,说白了就是个简化版的FTP。嵌入式开发中,它最常用的场景是:通过网络把内核镜像、设备树文件传给U-Boot。你想想看,总不能每次烧写都插拔SD卡吧?

2.3.1 安装与配置

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

# 创建TFTP根目录
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp

# 修改配置文件
sudo vim /etc/default/tftpd-hpa

配置文件内容:

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure --create"
注意:加上 --create 选项,这样U-Boot就能通过TFTP往服务器写文件了。我在调试内核时经常用这个功能保存日志。
# 重启服务
sudo systemctl restart tftpd-hpa
sudo systemctl enable tftpd-hpa

# 测试:放一个文件进去
echo "hello tftp" > /srv/tftp/test.txt

# 从本机测试下载
tftp localhost -c get test.txt

2.4 NFS服务配置

NFS(网络文件系统)是嵌入式开发中最常用的调试手段。说白了,就是把PC上的一个目录挂载到板子上,板子启动时直接从这个目录加载根文件系统。这样你改代码、编译、重启板子就能看到效果,不用反复烧写。

2.4.1 服务端配置

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

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

# 编辑导出文件
sudo vim /etc/exports

添加一行:

/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)
我曾经踩过的坑:no_root_squash 这个选项一定要加。不加的话,板子上的root用户会被映射成nobody,很多系统服务就跑不起来了。我当时调试一个udev问题,查了两天才发现是权限映射搞的鬼。
# 重启服务
sudo systemctl restart nfs-kernel-server

# 验证
showmount -e localhost

2.4.2 内核配置支持NFS启动

要让板子从NFS启动,内核必须开启以下选项:

CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y

U-Boot启动参数示例:

setenv bootargs 'console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.100:/srv/nfs/rootfs,v3,tcp ip=dhcp'
setenv bootcmd 'tftp 0x42000000 zImage; tftp 0x43000000 imx6ull.dtb; bootz 0x42000000 - 0x43000000'
boot

2.5 整体环境架构

下面这张图,是我做项目时常用的开发环境拓扑。你看一眼就能明白各个服务怎么配合:

嵌入式开发环境架构图 嵌入式开发环境架构图 开发主机 (Ubuntu) 交叉编译工具链 TFTP 服务器 /srv/tftp (zImage, dtb) NFS 服务器 /srv/nfs/rootfs 串口终端 (Minicom) 调试控制台 目标板 (ARM) U-Boot 启动 内核从TFTP加载 根文件系统从NFS挂载 串口输出调试信息 以太网 192.168.1.x 工作流程 1. 主机编译内核/应用 2. 内核通过TFTP下载 3. 根文件系统通过NFS挂载 4. 串口输出调试信息

2.6 环境验证清单

每次搭建完环境,我都会跑一遍这个清单,确保所有环节都通:

  1. 工具链验证:编译一个hello world,用 file 命令确认是ARM架构
  2. TFTP验证:从U-Boot用 tftp 0x42000000 zImage 下载文件,看速度是否正常
  3. NFS验证:板子启动后执行 mount,确认根文件系统来自NFS
  4. 串口验证:用Minicom或Putty连接,看内核启动日志是否完整

核心要点:

  • 发行版选Ubuntu LTS,跟厂商SDK对齐
  • 工具链用Linaro GCC,注意架构和ABI匹配
  • TFTP传内核,NFS挂根文件系统,串口看日志
  • 每次改环境都要跑一遍验证清单