LXR | KVM | PM | Time | Interrupt | Systems Performance | Bootup Optimization

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 启动系统"

 

posted on 2025-06-01 23:59  ArnoldLu  阅读(1206)  评论(0)    收藏  举报

导航