1. 为什么需要从零构建根文件系统?
很多刚接触TI AM5728这类高性能工业处理器的朋友,拿到开发板后,第一反应往往是直接使用厂商提供的现成系统镜像。这当然没问题,能快速上手。但当你真正想把这块板子用到自己的产品里,比如做个智能网关、视觉控制器或者边缘计算盒子时,现成的系统就开始“水土不服”了。
我遇到过最典型的情况是,项目需要一套极其精简的系统,只运行一个后台服务,但原厂镜像里塞满了各种用不上的图形界面、开发工具和测试软件,不仅占用宝贵的eMMC或SD卡空间,启动慢,还可能引入不必要的安全风险。又或者,你需要一个特定版本的软件库,而原厂镜像的软件源版本太旧,手动升级又常常遇到依赖地狱。这时候,从零开始构建一个量身定制的根文件系统,就成了必经之路。
所谓“根文件系统”,你可以把它理解成嵌入式Linux系统的“五脏六腑”和“家当”。内核负责驱动硬件、管理进程这些底层核心事务,而根文件系统则包含了系统运行所需的所有基础命令(比如ls、cp)、配置文件、库文件以及你的应用程序。它为整个系统提供了运行环境。为AM5728这样的ARM Cortex-A15/A7平台构建Ubuntu根文件系统,本质上就是在你的x86电脑上,为另一个架构的CPU准备一个完整的、可运行的软件家园。
这个过程听起来有点跨次元,但得益于qemu-user-static这样的神器,我们可以在自己的电脑里模拟出一个ARM环境,就像在电脑里开辟了一个独立的“ARM虚拟空间”,然后在这个空间里安装软件、配置系统,最后打包成一个完整的镜像,烧写到AM5728上就能直接跑起来。这么做的好处太多了:极度可控,系统里每一个软件都是你亲手挑选安装的;高度精简,没有一丝多余的赘肉;深度定制,从网络配置、用户权限到开机自启服务,完全按你的想法来。
接下来,我就带你走一遍我实战过多次的完整流程,从准备“建筑材料”(基础系统),到搭建“施工环境”(QEMU),再到“精装修”(安装软件、配置系统),最后“交付成品”(生成镜像)。我会把每一步的原理、操作命令和最容易踩的坑都讲清楚,确保你跟着做就能成功。
2. 准备构建环境与基础原料
工欲善其事,必先利其器。在开始“施工”前,我们需要准备好两样东西:一是构建系统所需的“原材料”,也就是最基础的Ubuntu文件系统;二是一个能在我们电脑(通常是x86_64架构)上运行ARM程序的“模拟施工队”。
2.1 获取Ubuntu基础文件系统:两种方法对比
获取ARM架构的Ubuntu基础文件系统,主要有两种主流方法,各有优劣,我两种都试过,下面给你详细拆解。
第一种方法:直接从Ubuntu官网下载基础包。 这是我最推荐新手使用的方法,简单、直接、速度快。Ubuntu官方提供了为嵌入式场景准备的“Ubuntu Base”镜像,这是一个非常精简的根文件系统,只包含最核心的包管理器(apt)、shell(bash)和最基本的工具。
操作起来很简单。打开浏览器,访问 http://cdimage.ubuntu.com/ubuntu-base/releases/。找到20.04 LTS(长期支持版)的目录,因为LTS版本稳定,支持周期长。对于AM5728这种带硬浮点单元的ARM处理器,我们选择 armhf 架构的版本。具体文件通常是 ubuntu-base-20.04.x-base-armhf.tar.gz。你可以直接在Ubuntu虚拟机里用wget命令下载:
wget http://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04.5-base-armhf.tar.gz
注意版本号可能会更新,以官网最新为准。这个方法下载的是一个已经编译打包好的基础系统,省去了从网络下载大量基础包的等待时间,特别适合国内网络环境。
第二种方法:使用debootstrap工具从头构建。
这个方法更“Geek”,也更具灵活性。debootstrap是一个工具,它的作用是从Ubuntu的软件仓库中,下载指定架构和版本的所有基础软件包,并在本地目录中组装成一个完整的根文件系统。理论上,你可以构建任何Ubuntu版本、任何架构的系统。
命令看起来是这样的:
sudo apt-get install debootstrap qemu-user-static binfmt-support
sudo qemu-debootstrap --arch=armhf --variant=minbase focal ./focal-armhf http://mirrors.ustc.edu.cn/ubuntu-ports/
这条命令分解一下:--arch=armhf指定架构;--variant=minbase指定构建一个最小化的基础系统;focal是Ubuntu 20.04的代号;./focal-armhf是目标目录;最后是软件源地址,这里用了中科大的镜像加速。
听起来很美好,对吧?但我必须给你泼盆冷水:除非你有非常好的国际网络环境,否则这个过程可能会极其缓慢甚至失败。因为它需要从软件源实时下载上百个软件包,而ubuntu-ports仓库对某些国内网络支持并不理想。我早期尝试时,经常卡在某个包下载上,一等就是半天。所以,对于大多数国内开发者,我强烈建议采用第一种方法,先拿到基础包,后续的定制工作在网络环境良好的chroot里进行,体验会好很多。
2.2 配置QEMU跨架构模拟环境
无论你用哪种方法拿到了基础文件系统的压缩包,解压后它只是一堆ARM架构的二进制文件。你没法直接在x86电脑上运行armhf的程序。这时候,qemu-user-static就闪亮登场了。
它的原理非常巧妙。Linux内核有一个叫binfmt_misc的机制,可以识别不同格式的可执行文件,并调用指定的解释器来运行它。qemu-user-static提供了一个静态编译的qemu-arm-static程序,它就是一个解释器。当我们把这个解释器放到ARM根文件系统的/usr/bin目录下,并通过binfmt_misc注册后,系统再遇到ARM程序时,就会自动调用qemu-arm-static来模拟执行。
安装和配置一气呵成:
# 安装必要的软件包
sudo apt-get update
sudo apt-get install qemu-user-static binfmt-support
# 解压基础文件系统 (假设你已经下载了tar包)
sudo mkdir -p ./am5728-rootfs
sudo tar -xpf ubuntu-base-20.04.x-base-armhf.tar.gz -C ./am5728-rootfs
# 将QEMU静态解释器复制到目标根文件系统中
sudo cp /usr/bin/qemu-arm-static ./am5728-rootfs/usr/bin/
复制qemu-arm-static这一步是关键!它相当于在ARM系统的“家”里放了一把万能钥匙(模拟器),这样我们后续用chroot“进入”这个家时,才能在里面正常执行apt-get install等命令。
这里有个小细节:解压时我用了 -p 参数(tar -xpf),这个参数会保留文件原有的权限属性,非常重要。根文件系统里很多文件(比如/bin/bash)需要有可执行权限,丢失了会导致系统无法启动。
3. 深入chroot环境:系统的“精装修”阶段
现在,我们有了一个空的“毛坯房”(基础根文件系统)和一把“钥匙”(qemu模拟器)。接下来,我们要进入这个房子内部,进行水电安装、墙面刷漆、家具进场,也就是安装软件和配置系统。chroot命令就是我们的“任意门”。
3.1 挂载虚拟文件系统与网络配置
直接chroot进去还不够,因为一个正在运行的Linux系统依赖于几个关键的虚拟文件系统,比如/proc(进程信息)、/sys(系统设备信息)、/dev(设备文件)。我们需要在chroot之前,把这些宿主机的虚拟文件系统“绑定挂载”到目标根文件系统的对应目录下。
我习惯用一个脚本来完成挂载和卸载,避免每次手动输入一长串命令。这个脚本通常叫ch-mount.sh,内容如下:
#!/bin/bash
MOUNT_DIR=$2
function mnt() {
echo "Mounting into $MOUNT_DIR"
sudo mount -t proc /proc ${MOUNT_DIR}proc
sudo mount -t sysfs /sys ${MOUNT_DIR}sys
sudo mount -o bind /dev ${MOUNT_DIR}dev
sudo mount -o bind /dev/pts ${MOUNT_DIR}dev/pts
# 复制DNS配置,保证chroot内能解析域名
sudo cp /etc/resolv.conf ${MOUNT_DIR}etc/resolv.conf
# 执行chroot
sudo chroot $MOUNT_DIR
}
function umnt() {
echo "Unmounting from $MOUNT_DIR"
sudo umount ${MOUNT_DIR}proc
sudo umount ${MOUNT_DIR}sys
sudo umount ${MOUNT_DIR}dev/pts
sudo umount ${MOUNT_DIR}dev
}
if [ "$1" == "-m" ] && [ -n "$2" ]; then
mnt $1 $2
elif [ "$1" == "-u" ] && [ -n "$2" ]; then
umnt $1 $2
else
echo "Usage:"
echo " $0 -m <mount_dir> # Mount and chroot"
echo " $0 -u <mount_dir> # Unmount"
fi
给脚本执行权限后,用它来挂载并进入我们的根文件系统:
sudo ./ch-mount.sh -m ./am5728-rootfs/
执行成功后,你的命令行提示符可能不会有明显变化,但此时你已经“穿越”到了为AM5728准备的ARM Ubuntu环境里了!你可以运行 uname -m 验证一下,应该会显示 armv7l。
第一个关键配置:换软件源。
默认的Ubuntu官方源在国外,在chroot环境里更新会慢得让你怀疑人生。第一步就是换成国内镜像源。这里我推荐中科大(ustc)或阿里云的源。
# 在chroot环境内执行
cat > /etc/apt/sources.list << EOF
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ focal main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ focal-updates main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ focal-security main restricted universe multiverse
EOF
注意URL中的 ubuntu-ports,这是专门为非x86架构(如ARM)准备的仓库分支,用错了会导致安装失败。
3.2 基础软件包安装与系统更新
配置好源,就可以开始安装软件了。首先更新软件包列表并升级现有软件:
apt-get update
apt-get upgrade -y
接下来,安装一些嵌入式系统必备的“生存包”。这个列表是我多年总结的,兼顾了实用性和精简性:
apt-get install -y \
sudo vim git curl wget \
net-tools iputils-ping ifupdown isc-dhcp-client \
ssh openssh-server \
udev systemd-sysv \
rsyslog kmod \
locales tzdata
- 网络工具:
net-tools(ifconfig)、iputils-ping、ifupdown是配置网络的基础。 - SSH:
openssh-server让你能远程登录,这是调试和管理的生命线。 - 设备管理:
udev负责动态创建设备节点,没有它,插上U盘或网卡系统可能识别不了。 - 日志与模块:
rsyslog记录系统日志,kmod用于加载内核模块。 - 本地化:
locales和tzdata设置语言环境和时区,避免时间错乱。
安装时务必加上 -y 参数,避免中途需要确认。这个过程会下载并安装不少包,取决于你的网络速度,需要耐心等待几分钟。
4. 针对AM5728的深度定制与配置
基础软件装好了,但这还是个“通用”的ARM系统。要让它能在AM5728开发板上跑得顺畅,还需要做一些针对性配置。
4.1 网络与主机名配置
嵌入式设备通常需要固定的IP或DHCP。我们配置一个以太网接口eth0使用DHCP,这适合大多数有路由器的场景。
# 创建网络接口配置文件
cat > /etc/network/interfaces.d/eth0 << EOF
auto eth0
iface eth0 inet dhcp
EOF
如果你需要静态IP,可以这样配置:
cat > /etc/network/interfaces.d/eth0 << EOF
auto eth0
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1
dns-nameservers 8.8.8.8
EOF
接着设置主机名,这会在命令行提示符和日志中显示:
echo "am5728-ubuntu" > /etc/hostname
echo "127.0.0.1 localhost am5728-ubuntu" >> /etc/hosts
4.2 用户、密码与安全基线
默认的根文件系统没有设置root密码,这是不安全的,也必须设置才能登录。
# 设置root密码,会提示你输入两次
passwd root
我强烈建议创建一个日常使用的普通用户,避免总是用root操作:
adduser engineer
# 按照提示设置密码、全名等信息
# 将用户加入sudo组,使其拥有管理员权限
usermod -aG sudo engineer
一个关键的安全设置:禁用串口调试登录。AM5728开发板通常通过串口连接。在/etc/systemd/system/getty.target.wants/目录下,你会找到一个类似serial-getty@ttyS0.service的链接。如果你不需要从串口登录,可以移除它,避免安全漏洞:
systemctl disable serial-getty@ttyS0.service
4.3 安装与配置开发环境
根据你的项目需求,安装必要的运行时和开发工具。例如,如果你的应用是Python写的:
# 安装Python3及常用工具
apt-get install -y python3 python3-pip python3-venv
# 安装一些常用的Python库
pip3 install --no-cache-dir numpy pyserial
如果需要C/C++开发环境:
apt-get install -y build-essential cmake git gdb
对于需要Java运行环境的:
apt-get install -y default-jdk-headless
注意:在嵌入式环境,尽量安装-headless版本(无图形界面依赖)的软件,以节省空间。
5. 清理、打包与生成最终镜像
系统配置得差不多了,是时候“封房验收”,准备交付给AM5728了。
5.1 退出chroot与清理工作
首先,在chroot环境内执行exit退出,回到宿主机的shell。然后,使用之前那个脚本卸载虚拟文件系统:
sudo ./ch-mount.sh -u ./am5728-rootfs/
重要! 在打包前,必须进行清理,以减小最终镜像体积。
- 清理APT缓存:
apt-get下载的软件包安装文件都缓存在/var/cache/apt/archives/,可以安全删除。sudo rm -rf ./am5728-rootfs/var/cache/apt/archives/*.deb sudo rm -rf ./am5728-rootfs/var/lib/apt/lists/* - 清理临时文件:
sudo rm -rf ./am5728-rootfs/tmp/* sudo rm -rf ./am5728-rootfs/var/tmp/* - 删除文档和手册(如果空间极其紧张):
sudo find ./am5728-rootfs/usr/share/doc -type f -delete sudo find ./am5728-rootfs/usr/share/man -type f -delete - 移除QEMU模拟器:这个只是构建时用的,板子上不需要。
sudo rm ./am5728-rootfs/usr/bin/qemu-arm-static
5.2 打包根文件系统并制作SD卡镜像
现在,将定制好的根文件系统目录打包成一个压缩包,方便传输和后续制作镜像。
sudo tar -czpf ubuntu-20.04-am5728-rootfs.tar.gz -C ./am5728-rootfs .
接下来,你需要将这个根文件系统放到一个完整的SD卡镜像中,这个镜像通常包含引导分区(存放U-Boot和内核设备树)和根文件系统分区。具体步骤依赖于你使用的SD卡制作工具和AM5728的引导方式。
以常见的使用mkimage和dd工具为例,假设你已经有一个预编译好的U-Boot (MLO, u-boot.img)、Linux内核(zImage)和设备树(*.dtb):
- 准备一个空镜像文件,并分区(通常第一个FAT分区放引导文件,第二个ext4分区放根文件系统)。
- 将引导文件拷贝到第一个FAT分区。
- 将我们制作的
ubuntu-20.04-am5728-rootfs.tar.gz解压到第二个ext4分区。 - 使用
dd命令将整个镜像写入SD卡。
由于不同厂商的AM5728核心板或开发板其引导流程和分区表可能有细微差别,这里不展开具体命令。最稳妥的方法是参考你所用硬件厂商提供的《系统烧写指南》,用你制作好的根文件系统压缩包替换掉他们指南中对应的那个文件。通常厂商会提供一个脚本(比如mk-sdcard.sh),你只需要把压缩包放在指定目录,运行脚本即可自动完成分区、格式化、拷贝和设置。
6. 上板测试与常见问题排坑
将烧写好的SD卡插入AM5728开发板,上电启动。通过串口调试终端,你应该能看到内核启动日志,最后出现登录提示符。用你设置的root或普通用户密码登录。
踩坑记录一:SSH登录失败
如果你安装了openssh-server却无法用SSH连接,提示密码错误。除了检查密码和网络,一个常见原因是SSH默认配置禁止root登录。你可以修改/etc/ssh/sshd_config文件:
PermitRootLogin yes
然后重启SSH服务:systemctl restart sshd。
踩坑记录二:系统时间不对
如果系统时间显示的是UTC时间或非常奇怪的时间,是因为没有正确设置时区。在构建时我们安装了tzdata,可以在板子上运行dpkg-reconfigure tzdata交互式选择时区,或者用非交互方式设置:
echo "Asia/Shanghai" > /etc/timezone
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
踩坑记录三:图形界面(如果需要)
如果你安装了桌面环境(如xubuntu-desktop),但启动后黑屏或无法进入桌面,很可能是显示驱动或显示管理器的问题。对于AM5728,TI的GPU驱动可能需要额外的固件或配置。对于大多数嵌入式应用,我建议不要安装完整的桌面环境,而是根据需要安装轻量级的窗口管理器或直接运行基于Qt、GTK的图形应用,这能节省大量资源并提高稳定性。
构建一个完全属于自己的根文件系统,第一次成功启动的那一刻成就感十足。整个过程就像在虚拟世界里为另一块芯片精心打造一个家园,每一个软件、每一项配置都了然于胸。当你的定制系统在AM5728上稳定运行时,那种对系统的掌控感,是使用现成镜像无法比拟的。后续你可以把这个根文件系统压缩包作为模板,为不同的项目快速衍生出新的定制版本,开发效率会大大提升。

149

被折叠的 条评论
为什么被折叠?



