Ubuntu(1):构建自己的Ubuntu发行版(ARM64)并使用QEMU测试
针对 ARM64 (AArch64) 架构优化的嵌入式Ubuntu构建与测试指南,包含完整构建流程和QEMU测试方案。
1 交叉编译环境配置
安装ARM64工具链:
sudo apt update sudo apt install gcc-aarch64-linux-gnu build-essential \ qemu-system-arm qemu-efi-aarch64 qemu-utils \ flex bison libssl-dev bc debootstrap # 验证工具链 aarch64-linux-gnu-gcc --version
2 构建最小化ARM64根文件系统
2.1 debootstrap
debootstrap 是 Debian/Ubuntu 系统中用于构建最小根文件系统的核心工具,特别适用于创建 chroot 环境、容器镜像或系统恢复环境。不要求宿主系统与目标系统相同(可跨架构构建)。
命令格式:
sudo debootstrap [选项] <发行版> <目标目录> [镜像URL]
架构选择 (--arch)
--arch=arm64 # ARM64 设备 (树莓派/服务器) --arch=amd64 # 标准 64-bit PC
系统变体 (--variant):
| 变体 | 大小 | 包含内容 | 用途 |
|---|---|---|---|
minbase |
~80MB | 绝对最小系统 (仅 apt/dpkg) | 容器基础层 |
buildd |
~200MB | 包含编译工具链 (gcc, make) | 软件编译环境 |
standard |
~500MB | 基础命令行工具 (vim, sudo) | 轻量级服务器 |
- (默认) |
~1GB | 标准桌面工具 | 普通系统 |
软件包控制:
--include=nginx,postgresql-15 # 预装指定包
--exclude=snapd,unattended-upgrades # 排除特定包
--components 是 debootstrap 命令中用于指定软件仓库组件的关键选项,它决定了安装过程中包含哪些类别的软件包。在 Debian/Ubuntu 系统中,软件仓库被划分为不同的组件(components),每个组件包含特定类型的软件包。
| 组件 | 包含内容 | 是否默认包含 |
|---|---|---|
main |
官方维护的自由开源软件(受 Ubuntu 完全支持) | ✓ |
universe |
社区维护的自由开源软件(质量有保障但无官方支持) | ✗ |
restricted |
专有硬件驱动程序(如显卡驱动) | ✗ |
multiverse |
受版权/法律限制的软件(非自由软件) | ✗ |
partner |
Canonical 合作伙伴的商业软件(需单独启用) | ✗ |
常见发行版本:
| 代号 | 版本 | 状态 |
|---|---|---|
jammy |
22.04 LTS | 长期支持 |
focal |
20.04 LTS | 长期支持 |
noble |
24.04 LTS | 最新LTS |
2.2 chroot
chroot(Change root)用于将当前进程的根目录切换到指定路径,创建一个隔离的"虚拟根环境"。
使 `/new/root` 成为进程的根目录 `/`,并执行[command]命令:
sudo chroot /new/root [command]
相关方案对比:
| 工具 | 隔离级别 | 复杂度 | 启动速度 | 典型用途 |
|---|---|---|---|---|
chroot |
文件系统 | 低 | 即时 | 系统修复/软件构建 |
| Docker | 完整隔离 | 中 | 快 | 应用容器化 |
| LXC/LXD | 进程级隔离 | 中高 | 中等 | 系统容器 |
| 虚拟机 | 硬件级 | 高 | 慢 | 完整系统隔离 |
2.3 创建根文件系统
创建目标目录:
export ROOTFS_DIR=~/arm64-rootfs
mkdir -p $ROOTFS_DIR
使用debootstrap构建基础系统:
sudo debootstrap --arch=arm64 \ --components=main,universe \ --include=ubuntu-minimal,systemd-sysv,net-tools,ssh \ jammy $ROOTFS_DIR \ http://ports.ubuntu.com/ubuntu-ports
支持的ubuntu包配置包括:
| 元包名称 | 作用描述 | 是否推荐包含 |
|---|---|---|
ubuntu-minimal |
核心最小系统 (必选) | ✓ 强烈推荐 |
ubuntu-standard |
标准命令行工具 (vim, man, curl) | ✓ 推荐 |
ubuntu-server |
服务器额外工具 (ssh, rsync) | 按需选择 |
ubuntu-desktop |
完整桌面环境 (GUI) | 桌面环境时用 |
基础系统配置:
sudo chroot $ROOTFS_DIR /bin/bash << 'EOF' echo "root:rootpass" | chpasswd echo "ubuntu-arm64" > /etc/hostname echo "nameserver 8.8.8.8" > /etc/resolv.conf echo "/dev/vda1 / ext4 defaults 0 1" > /etc/fstab ln -sf /usr/share/zoneinfo/UTC /etc/localtime apt-get update -y DEBIAN_FRONTEND=noninteractive apt-get install -y systemd-sysv udev net-tools iproute2 mkdir -p /etc/systemd/system/serial-getty@ttyAMA0.service.d cat > /etc/systemd/system/serial-getty@ttyAMA0.service.d/override.conf << 'END' [Service] ExecStart= ExecStart=-/sbin/agetty -o '-p -f -- \\u' --keep-baud 115200,38400,9600 --noclear --autologin root ttyAMA0 $TERM END exit EOF
3 编译ARM64 Linux内核(以6.5 LTS为例)
下载内核源码:
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.5.tar.xz tar xvf linux-6.5.tar.xz cd linux-6.5
配置内核:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
关键配置项(通过menuconfig启用):
编译内核和模块:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) Image.gz modules dtbs
4 创建可启动磁盘镜像
创建空白镜像文件(2GB):
qemu-img create -f qcow2 arm64-ubuntu.img 2G #镜像格式为qcow2。如果要写入eMMC设备,必须使用raw格式。
使用网络块设备(nbd)格式化并挂载镜像:
sudo modprobe nbd max_part=8 #加载nbd内核模块,允许将远程文件模拟成本地块设备。最多支持8个分区/dev/nbd0p1~p8。 sudo qemu-nbd -c /dev/nbd0 arm64-ubuntu.img #将arm64-Ubuntu.img文件通过NBD协议连接到/dev/nbd0块设备。
分区并格式化:
sudo parted /dev/nbd0 --script mklabel msdos #在/dev/nbd0上创建MBR分区表。--script表示非交互模式,自动执行命令。 sudo parted /dev/nbd0 --script mkpart primary ext4 1MiB 100% #创建一个占用整个磁盘的主分区,ext4格式。分区从1MiB开始,到磁盘末尾。分区设备名为/dev/nbd0p1。 sudo mkfs.ext4 /dev/nbd0p1 #将/dev/nbd0p1分区格式化为ext4文件系统。
挂载分区:
sudo mount /dev/nbd0p1 /mnt
复制根文件系统:
sudo cp -a $ROOTFS_DIR/* /mnt
安装内核和模块:
sudo make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \ INSTALL_MOD_PATH=/mnt modules_install sudo cp arch/arm64/boot/Image.gz /mnt/boot/vmlinuz-6.5.0-arm64 sudo cp arch/arm64/boot/dts/arm/*.dtb /mnt/boot/
创建fstab:
echo "/dev/vda1 / ext4 defaults 0 1" | sudo tee /mnt/etc/fstab
卸载镜像:
sudo umount /mnt sudo qemu-nbd -d /dev/nbd0 #断开镜像与/dev/nbd0的链接,确保数据写入镜像文件。
5 QEMU ARM64测试方案
5.1 QEMU启动命令
qemu-system-aarch64 \ -M virt \ -cpu cortex-a72 \ -smp 4 \ -m 2048 \ -kernel linux-6.5/arch/arm64/boot/Image.gz \ -drive file=arm64-ubuntu.img,format=qcow2,if=virtio \ -append "root=/dev/vda1 rw console=ttyAMA0" \ -netdev user,id=net0,hostfwd=tcp::2222-:22 \ -device virtio-net-device,netdev=net0 \ -nographic \ -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd
/usr/share/qemu-efi-aarch64/QEMU_EFI.fd 是 QEMU 虚拟机用于 ARM64 (aarch64) 架构的 UEFI 固件文件,属于开源 EDK II 项目的一部分。
5.2 调试与诊断
内核调试:
# 启动QEMU调试模式 qemu-system-aarch64 -s -S ... # 使用GDB连接 aarch64-linux-gnu-gdb vmlinux (gdb) target remote :1234 (gdb) hbreak start_kernel (gdb) continue
5.3 创建镜像和启动脚本
构建根文件系统;创建磁盘镜像;创建启动脚本:
#!/bin/bash # 1. 创建根文件系统 sudo apt update sudo apt install -y debootstrap qemu-system-arm qemu-utils sudo rm -rf ubuntu-rootfs mkdir ubuntu-rootfs sudo debootstrap --arch=arm64 --variant=minbase jammy ubuntu-rootfs http://ports.ubuntu.com/ubuntu-ports sudo cp /usr/bin/qemu-aarch64-static ubuntu-rootfs/usr/bin/ # 2. 非交互配置系统 (使用上述修改) sudo chroot ubuntu-rootfs /bin/bash << 'EOF' echo "root:rootpass" | chpasswd echo "ubuntu-mini" > /etc/hostname echo "nameserver 8.8.8.8" > /etc/resolv.conf echo "/dev/vda / ext4 defaults 0 1" > /etc/fstab ln -sf /usr/share/zoneinfo/UTC /etc/localtime apt-get update -y DEBIAN_FRONTEND=noninteractive apt-get install -y systemd-sysv udev net-tools iproute2 mkdir -p /etc/systemd/system/serial-getty@ttyAMA0.service.d cat > /etc/systemd/system/serial-getty@ttyAMA0.service.d/override.conf << 'END' [Service] ExecStart= ExecStart=-/sbin/agetty -o '-p -f -- \\u' --keep-baud 115200,38400,9600 --noclear --autologin root ttyAMA0 $TERM END exit EOF # 3. 提取内核和initrd # 4. 创建磁盘镜像 qemu-img create -f raw ubuntu-mini.img 2G mkfs.ext4 -F ubuntu-mini.img sudo mkdir -p /mnt/rootfs sudo mount -o loop ubuntu-mini.img /mnt/rootfs sudo cp -a ubuntu-rootfs/* /mnt/rootfs/ sudo umount /mnt/rootfs # 5. 创建启动脚本 cat > start.sh << 'END' #!/bin/bash qemu-system-aarch64 \ -machine virt \ -cpu cortex-a72 \ -smp 1 \ -m 1024 \ -kernel linux-6.5/arch/arm64/boot/Image.gz \ -append "root=/dev/vda rw console=ttyAMA0" \ -drive file=ubuntu-mini.img,format=raw,if=virtio \ -netdev user,id=net0,hostfwd=tcp::2222-:22 \ -device virtio-net-device,netdev=net0 \ -nographic END chmod +x start.sh echo "创建完成!使用 ./start.sh 启动系统"
浙公网安备 33010602011771号