制作ubuntu根文件系统

一个完整的Linux操作系统除了包括Linux内核之外,还必须依赖uboot,根文件系统等参与才能保证Linux从启动并正常运行

Ubuntu 的移植非常简单,不需要编译任何东西,因为Ubuntu 官方已经将根文件系统 制作好了!我们只需要简单配置一下 Ubuntu 官方提供的 base 根文件系统。

本文讲解如何根据ubuntu base来制作适合rk3506b开发板的根文件系统

下载ubuntu根文件系统

下载链接:Index of /

以正点原子的rk306b开发板为例,点击ubuntu-base -> realease -> 20.04,下载ubuntu-base-20.04.1-base-armhf.tar.gz

将压缩包copy进cd ubuntu2004_rootfs目录下,使用C参数解压到ubuntu20-rootfs目录中

1
2
sudo mkdir ubuntu20-rootfs
sudo tar -xvpf ubuntu-base-20.04.1-base-armhf.tar.gz -C ubuntu20-rootfs/

解压之后查看就是我们常见的文件系统目录,目前还不能直接使用,还需要对其做一些其他的配置

这里需要注意,上述解压以及后续的许多命令都要使用sudo权限,使用普通用户进行操作可能会导致文件属性丢失。比如上述tar命令中的p参数就是保留文件的原始权限和属性,这是系统根文件系统解压的关键选项

1
2
3
dky@LAPTOP-Q5IILQ3E:~/ubuntu2004_rootfs/ubuntu20-rootfs$ ls
bin dev home media opt root sbin srv tmp var
boot etc lib mnt proc run snap sys usr

安装qemu-user-static

可以使用qemu在wsl中挂载运行ubuntu-base这个根文件系统

1
2
sudo apt-get install qemu-user-static 
sudo cp /usr/bin/qemu-arm-static ubuntu20-rootfs/usr/bin/

备注说明

qemu-user-static

  1. 属于 “用户态仿真”(区别于 QEMU 全系统仿真),无需创建完整的虚拟机,无需额外配置内核,直接在当前主机的用户态环境中仿真其他架构的程序,轻量高效。
  2. 后缀static表示该工具是静态编译的,不依赖主机或目标根文件系统中的任何动态链接库(如libc.so),复制到 ARM 根文件系统后可直接运行,无需额外安装依赖,这对嵌入式根文件系统定制至关重要。
  3. 安装后,主机会在/usr/bin/目录下生成对应多种架构的仿真器二进制文件,其中qemu-arm-static就是专门用于仿真 ARM 架构 程序的工具。

安装目的:解决 “主机架构(通常是 x86/x86_64)与根文件系统架构(ARM)不兼容” 的问题 —— 如果不安装该工具,直接chroot进入 ARM 根文件系统后,执行任何命令都会报错无法执行二进制文件(因为主机无法识别 ARM 架构的程序指令)。

为什么要复制到根文件系统内部chroot命令的作用是 “切换根目录”,进入ubuntu20-rootfs/后,系统会将该目录作为新的 “/” 根目录,无法访问主机原有的/usr/bin/目录。因此,必须将qemu-arm-static复制到根文件系统的/usr/bin/目录中,才能在chroot环境中被调用。

复制后的效果:当chroot进入ubuntu20-rootfs后,执行任何 ARM 架构的命令(如apt updatels)时,系统会自动调用/usr/bin/qemu-arm-static来仿真执行 ARM 指令,从而在 x86 主机上正常运行 ARM 架构的程序,不会出现架构不兼容错误。


设置联网和软件源

1
sudo cp -b /etc/resolv.conf ubuntu-rootfs/etc/resolv.conf

b参数是安全复制,如果目标位置已经有resolv.conf文件则先备份一份

resolv.conf内容如下:

1
2
3
4
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 10.255.255.254

备注说明

resolv.conf是Linux 系统中的DNS(域名系统)配置文件,用于存储系统解析域名时依赖的 DNS 服务器地址(如 8.8.8.8(Google DNS)、114.114.114.114(国内通用 DNS)等)。

  1. 核心作用:系统通过该文件中的配置,将域名(如www.baidu.com)转换为可访问的 IP 地址,若该文件缺失或配置错误,系统将无法正常解析域名,只能通过 IP 地址访问网络(无法使用apt install等需要域名解析的命令)。

  2. 复制该文件的目的:将当前主机的有效 DNS 配置复制到嵌入式根文件系统中,让后续chroot进入该根文件系统时,能够直接继承可用的 DNS 配置,实现联网功能,方便进行软件安装、系统更新等定制化操作


编辑ubuntu20-rootfs/etc/apt/sources.list文件设置软件源

sources.list内容我并没有修改

1

在主机挂载并配置根文件系统

上面制作的根文件系统挂载到主机上,需要挂载 proc、sys、dev、dev/pts 等文件系统,最后使用 chroot 将主机的根文件系统切换到我们前面制作的根文件系统中。这里我们编写一个脚本,方便我们完成挂载和卸载操作,在 ubuntu-base(ubuntu2004_rootfs) 目录下编写一个挂载脚本mount.sh。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash
function mnt() {
echo "MOUNTING"
# 1. 挂载proc文件系统(进程/内核信息)
sudo mount -t proc /proc "${2}proc"
# 2. 挂载sysfs文件系统(硬件设备、内核驱动等信息),和proc类似,也是虚拟文件系统
sudo mount -t sysfs /sys "${2}sys"
# 3. 绑定挂载/dev目录(设备文件目录,如终端、磁盘等),-o bind是“绑定挂载”(镜像映射)
# 通过访问${2}dev(即它自己的/dev),就能间接访问主机的所有设备节点,相当于 “借用” 了主机的设备访问能力。
sudo mount -o bind /dev "${2}dev"
# 4. 绑定挂载/dev/pts目录(伪终端设备目录,支持chroot内的终端交互)
sudo mount -o bind /dev/pts "${2}dev/pts"
# 5. 挂载完成后,自动chroot进入目标根文件系统(${2}是目标根文件系统路径)
sudo chroot "${2}"
}

function umnt() {
echo "UNMOUNTING"
sudo umount "${2}proc"
sudo umount "${2}sys"
sudo umount "${2}dev/pts"
sudo umount "${2}dev"
}

if [ "$1" == "-m" ] && [ -n "$2" ]; then
mnt "$1" "$2"
elif [ "$1" == "-u" ] && [ -n "$2" ]; then
umnt "$1" "$2"
else
echo "用法: $0 -m /path/to/chroot/ 或 $0 -u /path/to/chroot/"
fi

接着给予 mount.sh 脚本可执行权限,命令如下:

1
sudo chmod 777 mount.sh

执行 mount.sh 脚本,将制作的根文件系统挂载到主机下

1
./mount.sh -m ubuntu20-rootfs/

如果退出需要执行exit命令

挂在成功后可以看到正在执行这个根文件系统了,可以执行一些简单得命令做个测试

1
2
3
4
5
6
7
8
9
10
11
dky@LAPTOP-Q5IILQ3E:~/ubuntu2004_rootfs$ ./mount.sh -m ubuntu20-rootfs/
MOUNTING
root@LAPTOP-Q5IILQ3E:/# ls
bin dev home media opt root sbin srv tmp var
boot etc lib mnt proc run snap sys usr
root@LAPTOP-Q5IILQ3E:/# whoami
root
root@LAPTOP-Q5IILQ3E:/# lsb
lsb_release lsblk
root@LAPTOP-Q5IILQ3E:/# lsb_release
No LSB modules are available.

image-20260117001910756

安装常见工具

1
2
3
4
5
6
apt update
apt upgrade
apt install sudo
apt install vim
apt install sudo
apt install net-tools ethtool ifupdown iputils-ping openssh-server

安装ubuntu桌面环境

这是制作根文件系统中最关键的一个环节,尽管只有一条命令

1
apt install ubuntu-desktop

这个安装包非常大,有2个多g。

在安装的时候会有一些时区,语言,键盘等之类的配置,截图如下:

image-20260116163010282

image-20260116163037650

设置开机默认切换到图形化界面

1
systemctl set-default graphical.target

image-20260116162927728

设置root用户和密码

1
passwd root

退出回到wsl主机

1
exit

image-20260116163241862

打包镜像

新建mkimage.sh文件并设置可运行权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/bin/bash

rootfs_dir=$1
rootfs_file=$2
rootfs_mnt="mnt"

if [ -z "$rootfs_dir" ] || [ -z "$rootfs_file" ]; then
echo "Usage: $0 [source_dir] [target_img]"
echo "Folder or target is empty."
exit 1
fi

if [ -f "$rootfs_file" ]; then
echo "-- Delete exist $rootfs_file ..."
rm -f "$rootfs_file"
fi

echo "-- Create $rootfs_file ..."
# 创建一个 6GB 的镜像文件
dd if=/dev/zero of="$rootfs_file" bs=1M count=6144
sudo mkfs.ext4 -F -L linuxroot "$rootfs_file"

# 3. 创建挂载点
if [ ! -d "$rootfs_mnt" ]; then
mkdir -p "$rootfs_mnt"
fi

echo "-- Copy data to $rootfs_file"
# 4. 挂载并拷贝
sudo mount "$rootfs_file" "$rootfs_mnt"
# 使用 -a (archive) 包含 -p,能更好保留权限
sudo cp -rfp "$rootfs_dir"/* "$rootfs_mnt/"

sudo sync
echo "-- Unmounting..."
sudo umount "$rootfs_mnt"
rm -rf "$rootfs_mnt"

echo "-- Resize $rootfs_file"
# 5. 检查并收缩镜像体积
/sbin/e2fsck -p -f "$rootfs_file"
/sbin/resize2fs -M "$rootfs_file"

echo "-- Done."

执行

1
./mkimage.sh ubuntu20-rootfs rootfs.img

等待打包完成后会在当前目录生成 rootfs.img 镜像文件

image-20260117002736358

烧录

接下来以windows下使用RKDevTool工具烧录为例

parameter.txt内容修改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
FIRMWARE_VER:8.1
MACHINE_MODEL:RK3506
MACHINE_ID:007
MANUFACTURER: RK3506
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 3506
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
GROW_ALIGN: 0
CMDLINE:mtdparts=:0x00002000@0x00002000(uboot),0x00000800@0x00004000(misc),0x00000200@0x00004800(vnvm),0x00007000@0x00004A00(recovery),0x00005000@0x0000BA00(boot),0x00990000@0x00010A00(rootfs),0x00008000@0x009A0A00(oem),-@0x009A8A00(userdata:grow)
uuid:rootfs=614e0000-0000-4b53-8000-1d28000054a9

按住maskroom按键,并按reset按键进入maskroom模式,烧录时存储注意选择emmc

img

选中并点击执行按钮烧录完成之后便会从SD卡重启

至此大功告成