1. 为什么你需要一个定制化的ARM Ubuntu系统?
如果你玩过树莓派、香橙派,或者用过NVIDIA Jetson这类开发板,那你对“刷系统”肯定不陌生。通常的做法是去官网下载一个现成的镜像,用工具烧录到SD卡里,插上就能用。这很方便,对吧?但用久了,你可能会发现一些问题:系统版本太旧,想升级又怕出问题;预装了一大堆你用不着的软件,占空间还拖慢速度;或者你想为某个特定的硬件项目做深度优化,却发现无从下手。
这就是自己动手构建系统的价值所在。想象一下,你拿到一块全新的ARM开发板,就像拿到一块空白的画布。官方镜像好比一幅印刷好的风景画,虽然精美,但构图和色彩已经固定。而自己构建系统,则是从调色、打底稿开始,亲手绘制一幅完全符合你心意的作品。你可以决定系统里包含什么,不包含什么;内核参数怎么调,服务怎么启;甚至桌面环境用哪个,字体装什么。整个过程虽然前期麻烦点,但换来的是一个极度精简、高度可控、完全为你量身定做的开发环境。
我自己在嵌入式项目里就经常这么干。比如做一个工业网关,根本不需要图形界面,连python都不需要,只需要一个能跑我Go语言编译好的二进制文件的最小系统。用官方镜像,光是清理无用包就得花半天,还容易有残留。而用debootstrap从零构建,最终的系统镜像可能只有300MB,启动飞快,安全性也更高,因为每一个存在的软件包都是我明确要求安装的。
所以,这篇指南就是带你走一遍这个“从零绘制”的过程。我们不依赖任何现成的“风景画”,就从最基本的线条开始,一步步搭建起一个属于你自己的ARM Ubuntu王国。不用担心复杂,我会把每一步的原理和操作都掰开揉碎了讲,保证你跟着做就能成功。
2. 动手前的核心概念与准备工作
在开始敲命令之前,我们得先搞清楚几个关键概念,这样后面操作时心里才有底,遇到问题也知道去哪儿找原因。
引导、内核与根文件系统:操作系统的“铁三角” 一个能启动的Linux系统,通常由三部分组成,你可以把它们想象成火箭发射的三个阶段。
- 引导程序(Bootloader):这是第一阶段,比如U-Boot。它存储在板子的ROM、EEPROM或者SD卡的特殊分区里。板子上电后,CPU会先执行它。它的任务很简单:初始化最基础的硬件(比如内存、时钟),然后去存储设备(比如SD卡)上找到并加载第二阶段——Linux内核。它就像发射塔,负责把火箭(内核)推到预定轨道。
- Linux内核:这是第二阶段,也是系统的核心。引导程序把它加载到内存后,它就开始接管了。内核会解析设备树(
dtb文件,一个描述硬件拓扑结构的数据文件),驱动起CPU、内存、存储、网络等所有关键硬件。最后,它需要挂载一个“根文件系统”才能继续。内核就像是火箭的发动机和主控计算机。 - 根文件系统:这是第三阶段,也是我们这篇文章要亲手构建的部分。你可以把它理解为火箭的载荷舱,里面装着所有让系统变得有用的东西:
/bin下的命令工具(ls,cp)、/etc下的配置文件、/lib下的库文件,还有我们最终要用的各种开发工具。内核会挂载它,并运行其中的第一个程序(通常是/sbin/init),从此,用户空间的服务和应用就启动起来了。
我们的工作范围 这篇指南,我们聚焦在构建根文件系统。我们假设你已经有了可用的引导程序(比如U-Boot)和Linux内核(比如从板子供应商那里获取的,或者自己编译好的)。我们的任务,就是在一个“工作台”(你现有的电脑系统)上,为ARM板子准备好一个干净、完整的Ubuntu根文件系统,然后把它烧录到目标存储设备上。
至关重要的准备工作 在开始构建前,请确保你的“工作台”环境符合要求:
- 一个可用的Linux系统:这可以是你的物理机(比如一台装好Ubuntu的电脑),也可以是一个虚拟机。我个人的习惯是在Windows上用VMware跑一个Ubuntu虚拟机,这样非常方便,不怕把宿主机搞乱。
- 足够的磁盘空间:构建过程会下载和生成大量文件,建议为这个项目预留至少5GB的可用空间。
- 稳定的网络连接:我们需要从Ubuntu的软件源下载大量的包。
- 目标存储设备:最后我们要把系统烧录进去。这可以是一张SD卡(通过读卡器连接电脑),也可以是开发板上的eMMC(通常通过USB连接电脑进入烧录模式)。在操作前,请务必确认设备名,比如是
/dev/sdb还是/dev/mmcblk0。操作错误的目标设备会导致数据丢失! 一个安全的习惯是,在插入设备前后,都用lsblk命令查看一下磁盘列表的变化。
好了,理论铺垫完成,我们的“工作台”也准备好了。接下来,就进入最核心的环节——使用debootstrap这个神奇的工具,来搭建系统的骨架。
3. 使用Debootstrap构建最小化根文件系统
debootstrap是Debian/Ubuntu系统下的一个神器,它的作用就是从网络上的软件仓库中,下载指定架构和版本的系统最核心的软件包,并在本地目录中组装出一个可运行的最小系统。这就像是从乐高官方仓库里,只领取搭建一座城堡所必需的基础砖块和核心框架。
第一步:安装debootstrap工具 在你的工作台系统(我们称之为“宿主系统”)里,打开终端,首先安装这个工具:
sudo apt-get update
sudo apt-get install debootstrap
很简单,两条命令搞定。apt-get update是刷新软件源列表,确保我们能获取到最新的信息。
第二步:运行debootstrap命令 这是最关键的一步。假设我们打算为一块64位的ARM开发板(比如树莓派3/4,RK3399等)构建系统,我们选择Ubuntu 20.04 LTS(Focal Fossa)这个长期支持版本,因为它既稳定又有较新的软件包。
sudo debootstrap --arch=arm64 --variant=minbase focal /opt/arm-ubuntu http://ports.ubuntu.com/ubuntu-ports/
我来详细解释一下这个命令的每个部分:
--arch=arm64:指定目标系统的CPU架构为ARM 64位。如果你的板子是32位的ARM(比如老款的树莓派1/2,全志H3芯片),这里需要改为armhf。--variant=minbase:指定变体为“最小基础”。这个变体只安装apt,libc,dpkg等绝对必要的包,生成的系统非常精简。如果你想包含更多常用工具(如systemd-sysv,ubuntu-minimal),可以使用buildd或--variant=standard。focal:这是Ubuntu 20.04的版本代号。如果你想用18.04(Bionic)或22.04(Jammy),替换成对应的代号即可。/opt/arm-ubuntu:这是宿主系统上的一个目录路径,用于存放即将构建出来的根文件系统。你可以把它放在任何你有写权限的位置,比如/home/yourname/rootfs。请确保这个目录是空的,或者之前构建的残留内容可以被覆盖。http://ports.ubuntu.com/ubuntu-ports/:这是Ubuntu官方为ARM等非x86架构设立的软件源镜像。在国内,为了更快的下载速度,我强烈建议替换为国内镜像源,例如:- 中国科学技术大学:
http://mirrors.ustc.edu.cn/ubuntu-ports/ - 清华大学:
https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/
- 中国科学技术大学:
命令执行后,你会看到终端开始疯狂滚动,下载并安装一个个基础包。这个过程视网络情况,可能需要10到30分钟。完成后,你会看到“I: Base system installed successfully.”之类的提示。
第三步:进入“沙盒”——Chroot环境配置
现在,/opt/arm-ubuntu目录里已经有了一个完整的、但还“沉睡”着的ARM Ubuntu系统。为了进一步配置它(比如安装软件、设置密码),我们需要“进入”这个系统。但由于它的指令集(ARM)和宿主系统(很可能是x86_64)不同,我们不能直接运行里面的程序。这时,就需要chroot(Change Root)来帮忙。
chroot可以改变进程及其子进程的根目录,让它们认为/opt/arm-ubuntu就是真正的/。但为了让这个“沙盒”内的系统能正常访问设备、进程信息等,我们还需要挂载几个关键的虚拟文件系统:
# 挂载虚拟文件系统到目标根目录下
sudo mount -t proc /proc /opt/arm-ubuntu/proc
sudo mount -t sysfs /sys /opt/arm-ubuntu/sys
sudo mount -o bind /dev /opt/arm-ubuntu/dev
sudo mount -o bind /dev/pts /opt/arm-ubuntu/dev/pts # 伪终端支持,很重要
# 复制宿主系统的DNS解析配置,让chroot环境内可以上网
sudo cp /etc/resolv.conf /opt/arm-ubuntu/etc/resolv.conf
现在,我们可以进入这个沙盒了:
sudo chroot /opt/arm-ubuntu /bin/bash
执行成功后,你的命令行提示符可能会变成类似 root@hostname:/# 的样子。注意,你现在已经“身处于”那个ARM系统之中了!接下来所有的操作,都是针对这个即将被烧录到开发板上的系统。
4. 在Chroot环境中进行基础配置
现在,我们就在这个ARM系统的“内部”了。让我们来给它注入灵魂,安装一些让它真正能用的基础软件和配置。
4.1 更新软件源并安装核心工具
首先,更新一下软件包列表。虽然debootstrap刚下载完,但更新一下总没错。
apt-get update
接下来,安装一些没有它简直寸步难行的工具:
sudo:允许普通用户执行特权命令。net-tools,iproute2:包含ifconfig,route,ip等命令,用于网络配置和诊断。iproute2是现代Linux更推荐的工具集。dhcpcd或network-manager:用于自动获取IP地址。对于服务器或固定环境,dhcpcd更轻量。vim或nano:文本编辑器。总不能一直用cat和echo来改文件吧?我习惯装vim。wget,curl:网络下载工具。
apt-get install -y sudo net-tools iproute2 dhcpcd5 vim wget curl
-y参数表示自动确认安装,避免中途需要手动输入Y。
4.2 设置Root密码和创建用户
一直用root用户不安全,我们创建一个日常使用的普通用户,并赋予它sudo权限。
# 1. 为root用户设置一个强密码
passwd
# 然后根据提示输入两次新密码。
# 2. 创建一个新用户,比如叫 ‘developer’
adduser developer
# 这条命令会交互式地让你设置密码、填写全名等信息,一路回车用默认值也可以。
# 3. 将新用户添加到 sudo 组,使其拥有管理员权限
usermod -aG sudo developer
这样,以后登录就可以用developer用户,需要安装软件时再用sudo提权。
4.3 配置系统基础信息
- 主机名:给你的板子起个名字,比如
my-arm-dev。echo "my-arm-dev" > /etc/hostname # 同时更新hosts文件,让系统能解析自己的名字 echo "127.0.1.1 my-arm-dev" >> /etc/hosts - 时区:设置为亚洲上海时间(即北京时间)。
ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # 然后配置系统时钟服务(如果安装了systemd) apt-get install -y systemd-sysv # 如果之前是最小安装,可能需要这个 dpkg-reconfigure -f noninteractive tzdata - 语言环境:安装中文本地化支持,避免终端显示乱码。
apt-get install -y locales # 生成并设置中文UTF-8环境 locale-gen zh_CN.UTF-8 update-locale LANG=zh_CN.UTF-8
4.4 配置Fstab文件
/etc/fstab文件定义了系统启动时需要自动挂载的分区。我们需要根据目标存储设备的分区计划来预先配置它。假设我们计划给SD卡分三个区:
/dev/mmcblk0p1-> 挂载到/boot(FAT32格式,存放内核和DTB)/dev/mmcblk0p2-> 挂载到/(ext4格式,根文件系统)/dev/mmcblk0p3-> 作为交换分区swap
那么,编辑/etc/fstab文件:
vim /etc/fstab
添加如下内容(注意:设备名mmcblk0pX需要根据你实际的分区结果调整,使用blkid命令可以查看分区的UUID,用UUID代替设备名是更稳定的做法):
# <file system> <mount point> <type> <options> <dump> <pass>
/dev/mmcblk0p1 /boot vfat defaults 0 2
/dev/mmcblk0p2 / ext4 errors=remount-ro 0 1
/dev/mmcblk0p3 none swap sw 0 0
配置完成后,输入 exit 退出chroot环境,然后回到宿主系统,卸载之前挂载的虚拟文件系统:
exit
sudo umount /opt/arm-ubuntu/dev/pts
sudo umount /opt/arm-ubuntu/dev
sudo umount /opt/arm-ubuntu/sys
sudo umount /opt/arm-ubuntu/proc
至此,一个包含了基本配置的、可定制的ARM Ubuntu根文件系统就已经在/opt/arm-ubuntu目录下准备就绪了。它已经是一个功能完整的系统核心,接下来就是把它“移植”到目标设备上。
5. 分区、烧录与首次启动
现在,我们有了精心制作的根文件系统,是时候把它写入到SD卡或eMMC,让开发板能跑起来了。这一步需要格外小心,因为操作对象是物理存储设备。
5.1 连接并识别目标设备
将你的SD卡通过读卡器插入电脑(或者将开发板设置为eMMC烧录模式并通过USB连接)。在终端里使用lsblk命令查看块设备列表。
lsblk
仔细辨认哪个是新出现的设备。比如,你的电脑硬盘可能是/dev/sda,插入的SD卡可能显示为/dev/sdb。请务必确认无误,因为下一步的格式化操作会清除该设备上的所有数据。
5.2 对存储设备进行分区
我们将使用fdisk或更易用的parted工具进行分区。这里以fdisk操作/dev/sdb为例(请根据你的实际情况替换设备名!)。
sudo fdisk /dev/sdb
进入fdisk交互界面后:
- 输入
o然后回车,创建一个新的DOS分区表(对于大多数ARM板,MSDOS分区表兼容性更好。如果是UEFI启动的AArch64板子,可能需要g创建GPT分区表)。 - 输入
n创建新分区,选择p主分区,分区号1,起始扇区默认,大小设置为+512M(创建一个512MB的boot分区)。 - 再次输入
n创建第二个主分区,分区号2,起始扇区默认,大小设置为+8G(根据你的卡大小调整,建议根分区不小于4GB)。 - 再次输入
n创建第三个主分区,分区号3,起始扇区默认,大小直接回车使用所有剩余空间(作为swap交换分区)。 - 输入
t然后选择分区号1,将类型设置为c(W95 FAT32 (LBA)),这是boot分区常用的格式。 - 输入
t选择分区号3,将类型设置为82(Linux swap)。 - 输入
p查看分区表,确认无误。 - 最后,输入
w将分区表写入磁盘并退出。
分区完成后,系统可能会自动识别新分区。如果没有,可以执行sudo partprobe /dev/sdb通知系统重新读取分区表。
5.3 格式化分区并烧录系统
现在,我们有三个分区:/dev/sdb1 (boot), /dev/sdb2 (root), /dev/sdb3 (swap)。分别对它们进行格式化。
# 格式化boot分区为FAT32
sudo mkfs.vfat -F 32 -n BOOT /dev/sdb1
# 格式化root分区为ext4,并添加标签
sudo mkfs.ext4 -L ROOTFS /dev/sdb2
# 初始化swap分区
sudo mkswap /dev/sdb3
接下来,开始烧录内容:
- 烧录Boot分区:这个分区需要放入你的Linux内核镜像(
Image或zImage)、设备树文件(.dtb)、以及可能需要的U-Boot引导文件。假设你把这些文件都准备在了宿主系统的~/kernel-output/目录下。# 挂载boot分区 sudo mount /dev/sdb1 /mnt # 拷贝内核相关文件 sudo cp ~/kernel-output/Image ~/kernel-output/*.dtb /mnt/ # 如果有U-Boot,可能还需要拷贝boot.scr等文件 # 卸载 sudo umount /mnt - 烧录根文件系统:这就是我们之前构建的成果。
# 挂载root分区 sudo mount /dev/sdb2 /mnt # 使用rsync同步,它能更好地保留文件属性、权限和符号链接 sudo rsync -avh /opt/arm-ubuntu/ /mnt/ # 同步完成后,卸载 sudo umount /mnt - 启用Swap分区:这一步不是必须的,但对于内存小的板子有帮助。
sudo swapon /dev/sdb3
5.4 首次启动与验证
将烧录好的SD卡插入开发板,连接串口调试线(这是观察启动过程最直接的方式),上电。
你应该能在串口终端里看到U-Boot的启动日志,接着是Linux内核的启动信息,最后如果一切顺利,会出现登录提示符 my-arm-dev login:。
用之前创建的developer用户和密码登录。登录后,可以运行一些命令验证:
uname -a # 查看内核架构,应该是aarch64或armv7l
df -h # 查看磁盘挂载情况,确认/和/boot分区已正确挂载
ip addr # 查看网络接口,试试ping一下外网
sudo apt update # 测试软件源和网络是否正常
恭喜你!一个由你亲手定制的最小化ARM Ubuntu系统已经成功运行起来了。它现在是一个干净的基础,接下来你可以根据开发需求,把它打造成任何你想要的样子。
6. 进阶定制:安装图形界面与开发环境
一个只有命令行的系统对于嵌入式产品可能足够了,但作为开发环境,我们常常需要图形界面来运行IDE、浏览器查资料,或者进行图形化调试。此外,安装完整的开发工具链也是必须的。让我们继续完善它。
6.1 安装轻量级图形桌面环境 对于资源有限的ARM板,像GNOME或KDE这样的全功能桌面太重了。我强烈推荐Xfce或LXQt,它们功能完整但非常轻量。这里以Xfce为例。
首先,确保你在开发板的系统内(通过串口或SSH登录),然后更新软件包列表并安装Xfce:
sudo apt-get update
sudo apt-get install -y xfce4 xfce4-goodies
xfce4-goodies包含了一些额外的插件和实用程序,让桌面更好用。安装过程可能会比较长,因为它要下载很多包,请耐心等待。
6.2 安装显示管理器和中文支持
光有桌面环境还不够,我们需要一个显示管理器(Display Manager)来提供图形登录界面。lightdm是一个轻量且流行的选择。
sudo apt-get install -y lightdm
安装过程中,它会提示你选择默认的显示管理器,用方向键选择lightdm并按回车确认。
为了让界面能显示中文,我们需要安装中文字体和输入法框架(如fcitx):
# 安装中文字体
sudo apt-get install -y fonts-wqy-zenhei fonts-wqy-microhei
# 安装fcitx输入法框架及中文输入法
sudo apt-get install -y fcitx fcitx-googlepinyin fcitx-config-gtk
安装后,需要配置环境变量。编辑用户配置文件~/.profile,在末尾添加:
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx
重启lightdm服务或直接重启系统,就能看到图形登录界面了。
sudo systemctl restart lightdm
6.3 安装核心开发工具 现在,让我们把这里变成一个真正的开发工作站。
- 构建工具链:如果你要进行本地编译(在ARM板上直接编译代码),需要安装
gcc,g++,make等。sudo apt-get install -y build-essential - 版本控制:
git是程序员必备。sudo apt-get install -y git - Python环境:Ubuntu通常预装了Python3,但我们可以安装
pip和虚拟环境管理工具。sudo apt-get install -y python3-pip python3-venv - 调试工具:
gdb用于调试,strace用于跟踪系统调用。sudo apt-get install -y gdb strace - 网络与文件传输工具:
openssh-server允许你通过SSH远程登录,rsync用于高效同步文件。sudo apt-get install -y openssh-server rsync sudo systemctl enable ssh # 设置开机自启
6.4 安装集成开发环境(IDE)
在ARM板上运行VS Code或CLion可能比较吃力,但有一些轻量级选择。例如,Geany是一个快速、小巧的IDE,支持多种语言。
sudo apt-get install -y geany
或者,如果你主要做Python开发,可以安装Thonny,这是一个对初学者非常友好的Python IDE。
sudo apt-get install -y thonny
当然,你也可以选择在宿主电脑上交叉编译,然后通过SSH和rsync将程序部署到板子上运行,这是嵌入式开发更常见的流程。这时,板子上的系统只需要具备运行环境即可,编译工具链可以不用装,进一步节省空间。
经过这一步,你的ARM Ubuntu已经从一个小巧的核心,成长为一个功能齐全、界面友好、随时可以投入开发的强大工作站。整个定制过程虽然步骤繁多,但每一步都让你对系统的掌控更深一层。下次当你需要为一个特定项目优化系统时,你就会知道从哪里入手,是删减不需要的服务,还是添加特定的驱动和库。这种“知其然更知其所以然”的体验,正是自己构建系统最大的乐趣和收获所在。

627

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



