build_embed_linux_system

基于debian构建文件系统

基于Buildroot我们已经可以较为轻松的构建可用的文件系统,不过在实际使用中还是不可避免的有所缺陷。

  1. 系统需要增加新的软件和库时,需要重新构建系统或从源码编译移植。
  2. Buildroot一定程度解决了包、编译器和系统之间的兼容性问题。不过对于不同版本(如Ubuntu18.04、Ubuntu22.04),不同类型(如Fedora系统)的系统,编译问题仍然存在,且难度随着包支持增多而显著增加。
  3. Buildroot支持的包虽然很多,不过仍然很难覆盖全面,一些小众需求的移植仍然困难。

对于桌面端Ubuntu、Centos系统来说,除了第三方源码编译外,最主要的软件安装方式其实和Windows平台类似。使用离线包(dpkg)或在线安装(apt,yum)这两种方式。对于嵌入式设备来说,其原理上差异不大,理论上当然也支持;将编译构建完成的系统以软件包的形式存储在服务器中,通过命令下载、解压、构建、提供二进制格式的软件离线和在线安装包支持;Debian系统正是基于这一理念设计的。不过因为支持功能增多,Debian也会占用更多资源,所以一般用于更高性能的SOC。

本节目录如下所示。

debian_ver

debian系统的版本说明如下所示。

本例在桌面端Ubuntu22.04系统中使用bookworm版本的Debian进行构建,其它版本需要自己验证修改。

注意: Ubuntu也是基于debian进行深度定制的系统,每个版本都基于debian系统生成。理论上每个版本的Ubuntu都可以构建所有的Debian系统。不过考虑到实际兼容性,以及支持环境的不同,桌面端Ubuntu版本和需要构建的debian的版本最好保持版本一致,这样可以避免很多兼容性问题。这里以debian-bookworm为例,桌面端版本选择Ubuntu 22.04 LTS,也是本系列文章选择的系统。

Ubuntu版本 Ubuntu代号 Debian代号 Debian版本
24.04 LTS Noble trixie/sid 13
23.10 Mantic trixie/sid 13
23.04 Lunar bookworm/sid 12
22.04 LTS jammy bookworm/sid 12
21.10 Impish bullseye/sid 11
20.04 LTS Focal bullseye/sid 11
19.10 Eoan buster/sid 10
18.04 LTS Bionic buster/sid 10
17.10 Artful stretch/sid 9
16.04 LTS xenial stretch/sid 9
15.10 Wily jessie/sid 8
14.04 LTS Trusty jessie/sid 8

build_sh

构建Debian系统的流程包含如下流程。

  1. 通过debootstrap工具,在主机环境下进行stage-first步骤安装。
  2. 基于qemu和chroot的沙箱环境,在模拟的嵌入式环境下进行stage-second步骤安装。
  3. 安装完成后,执行必要的软件安装和环境处理,构建运行环境。

注: 作为通用平台系统,Debian在基本构建上适配大部分板级硬件,一般来说只分32/64位系统,以及输出串口的区别。

配置中主要修改项。

  1. OPT_OS_VER,对应Debian的版本,参考上面列出的版本说明。
  2. qemu_arch, 指定虚拟机工具qemu的版本,arm32位对应arm,arm64位对应aarch64
  3. CHIP_ARCH, 对应Debian工作的平台,armhf表示32位硬浮点,arm64表示64位平台,其它可选项可参考: https://mirrors.tuna.tsinghua.edu.cn/debian/dists/bookworm/main/ 中的binary的后缀,常用的类型目录如下所示。
CHIP_ARCH配置 对应的平台说明
amd64 64位x86版本系统
i386 32位x86版本系统
arm64 64位arm版本系统
armhf 32位arm硬浮点版本系统
armel 32位arm软浮点版本系统

本例程中以清华源的镜像构建debian文件系统,快速构建Debian系统的脚本如下所示。

# 定义构建时用到的参数
OPT_OS_VER=bookworm
CHIP_ARCH=armhf
qemu_arch=arm
NFS_PATH="/home/freedom/Desktop/user_git/sdk/nfs"

run_as_client() {
    $@ > /dev/null 2>&1
}

# 挂载系统目录到用户目录()
mount_chroot()
{
    sudo mount -t proc chproc "${NFS_PATH}"/proc
    sudo mount -t sysfs chsys "${NFS_PATH}"/sys
    sudo mount -t devtmpfs chdev "${NFS_PATH}"/dev || sudo mount --bind /dev "${NFS_PATH}"/dev
    sudo mount -t devpts chpts "${NFS_PATH}"/dev/pts
}

# 移除系统目录
umount_chroot()
{
    while grep -Eq "${NFS_PATH}.*(dev|proc|sys)" /proc/mounts
    do
        sudo umount -l --recursive "${NFS_PATH}"/dev >/dev/null 2>&1
        sudo umount -l "${NFS_PATH}"/proc >/dev/null 2>&1
        sudo umount -l "${NFS_PATH}"/sys >/dev/null 2>&1
        sleep 5
    done
}

# 1. 实现构建系统的必要环境
sudo apt-get install debootstrap debian-archive-keyring qemu-user-static -y

# 2. 使用debootstap完成从镜像源下载文件
if [ ! -d ${NFS_PATH}/bin/ ]; then
    sudo debootstrap --foreign --verbose  --arch=${CHIP_ARCH} ${OPT_OS_VER} ${NFS_PATH} http://mirrors.tuna.tsinghua.edu.cn/debian/
fi

# 安装qemu-*-static
sudo chmod -Rv 777 ${NFS_PATH}/usr/
cp /usr/bin/qemu-${qemu_arch}-static ${NFS_PATH}/usr/bin/
chmod +x ${NFS_PATH}/usr/bin/qemu-${qemu_arch}-static

# 基于debootstrap完成后续安装
cd ${NFS_PATH}
mount_chroot

# 3. 进行debootstrap第二部分的安装
LC_ALL=C LANGUAGE=C LANG=C sudo chroot ${NFS_PATH} /debootstrap/debootstrap --second-stage --verbose

# 安装必要的软件
LC_ALL=C LANGUAGE=C LANG=C sudo chroot ${NFS_PATH} apt-get install vim libatomic1 -y

umount_chroot

通过上述步骤就可以构建完成基于debian的系统。debian系统的安装主要有debootstrap命令完成,主要包含以下几部分。

  1. 通过debootstrap从镜像源下载文件,构成debian集成文件。
  2. 通过chroot配合qemu-x-static搭建模拟的嵌入式平台环境,通过debootstrap文件构建完整系统。
  3. 通过apt-get,dpkg等工具安装系统比较文件如vim,net-tools等。

脚本都是基于上述步骤完成。其中debootstrap理解比较简单,可以理解为下载安装工具;其功能就是从镜像源下载压缩包,解压并安装文件到指定目录。比较复杂的反而是chroot工具,它是Linux和类Unix系统中的一个命令,用于改变当前进程及其子进程的根目录;相当于在系统中单独创建一个隔离的执行环境,执行新系统应用。不过chroot最强大的部分还不止于此,其另一个用途是可以配合qemu工具,在x86环境下模拟一个嵌入式平台的运行环境,执行嵌入式平台的应用。正是依赖这一点,才能够完成debootstrap的第二部分安装以及必要的软件安装。

理解了这两个程序的用法,整个步骤就比较清晰可见了;构建debian系统也就没有秘密和难度可以,后续Ubuntu构建反而更近一步简化操作,相对来说更加简单。顺理成章就来到了第二节,使用chroot沙箱模式进行系统的定制化。

chroot_structure

本节主要使用chroot进入沙箱模式配置debian系统,实现用户定制的专属系统;其主要步骤如下所示。

  1. 通过chroot进入模拟嵌入式平台的沙箱模式。
  2. 安装定制系统必要的软件

enter_chroot

# 进入构建目录
cd "${NFS_PATH}"/

# 进入nfs系统
workdir=$(pwd)
sudo mount -t proc chproc "${workdir}"/proc
sudo mount -t sysfs chsys "${workdir}"/sys
sudo mount -t devtmpfs chdev "${workdir}"/dev || sudo mount --bind /dev "${workdir}"/dev
sudo mount -t devpts chpts "${workdir}"/dev/pts
LC_ALL=C LANGUAGE=C LANG=C sudo chroot "${workdir}"

image

customized_sys

在chroot环境中,使用apt-get安装必要的软件。

# 安装必要的软件
apt-get install vim net-tools dialog apt-utils -y

添加用户,增加用户管理。

# 增加用户
adduser freedom

# 添加密码

# 对于用户增加sudo使用权限
visudo

# +
freedom ALL=(ALL:ALL) ALL

增加串口打印服务,用于串口打印和系统命令输入。

# Debian默认只支持tty1输出,也就是屏幕,如果希望串口输出,增加相应服务
# 复制串口ttymxc0启动服务,所有步骤完成
cd /etc/systemd/system/getty.target.wants

# [ TIME ] Timed out waiting for device dev-ttymxc0.device. 
# 对于其它SOC芯片,需要将ttymxc0更新为相应的串口(例如ttyS1)
cp -d getty@tty1.service getty@ttymxc0.service

对于构建号的系统,后续打包成tar.gz或者img格式,就可以用于下载和运行。可以看到,debian系统的主要流程如下所示。

  1. 从服务器下载资源,解压并安装。
  2. 进入沙盒模式,进行下一步安装。
  3. 通过apt-get安装软件,然后配置用户和打印串口的支持。
  4. 最终打包成需要下载的文件格式,就可以用于最终下载。

至此,关于debian系统的初步构建实现完毕。

issue_fix

对于构建过程中的问题,整理了如下项,可根据实际情况确认解决。

issue_1

调用chroot时,显示/bin/bash: exec format error。

原因: chroot进入沙箱模式时,相当于在x86跨平台执行arm端的应用,需要arm虚拟机环境的支持。

解决办法:

# 确定是否安装qemu-user-static
sudo apt-get install qemu-user-static update-binfmts -y

# 如果确定安装,判断系统中是否支持开启binformat的支持
# 这个机制原理时内核通过检测文件的起始字节来确定调用的程序,如果未开启,使用命令开启
update-binfmts --display

# 如果发现qemu-arm未开启,使用如下命令开启,然后检测是否开启
update-binfmts --enable qemu-arm
update-binfmts --display

# 如果发现没有qemu-arm选项,此时还有最后的办法,自己导入支持
# 除非理解为什么这么做,而且知道表示含义,否则不要执行这一步,这一步会改变系统配置,如果写入
# 值有错,可能会导致数据损坏,大部分命令都无法启动
######################## 导入qemu-arm ############################
touch /usr/share/binfmts/qemu-arm

# 向文件中写入配置内容
cat << EOF | sudo tee /usr/share/binfmts/qemu-arm
package qemu-user-static
interpreter /usr/libexec/qemu-binfmt/arm-binfmt-P
magic \x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00
offset 0
mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
credentials yes
fix_binary yes
preserve yes
EOF

# 导入对armhf虚拟环境的支持
sudo update-binfmts --import /usr/share/binfmts/qemu-arm

######################## 导入qemu-aarch64 ############################
# 创建配置文件
sudo touch /usr/share/binfmts/qemu-aarch64

# 向文件中写入配置内容
sudo cat << EOF | sudo tee /usr/share/binfmts/qemu-aarch64
package qemu-user-static
interpreter /usr/libexec/qemu-binfmt/aarch64-binfmt-P
magic \x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00
offset 0
mask \xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
credentials yes
fix_binary yes
preserve yes
EOF

# 导入对aarch64虚拟环境的支持
sudo update-binfmts --import /usr/share/binfmts/qemu-aarch64

# 检查是否启用成功
update-binfmts --display

如下所示即为成功。

image

next_chapter

返回目录

直接开始下一章节说明: 基于ubuntu构建文件系统