--- title: 根文件系统构建 tags: [根文件系统, BusyBox, 嵌入式Linux, I.MX6ULL, 系统移植] created: 2026-09-16 updated: 2026-09-17 pdf_ref: "【正点原子】I.MX6U嵌入式Linux驱动开发指南V2.0.1 - 第三十八章 根文件系统构建" --- # 根文件系统构建 > 💡 **关联知识**: [[06-系统移植与启动/03-Linux内核裁剪与配置]] | [[02-嵌入式Linux内核基础/01-内核编译与启动流程]] | [[06-系统移植与启动/01-Uboot移植与配置]] ## 一、根文件系统概述 ### 1.1 什么是根文件系统 根文件系统(rootfs)是 Linux 内核启动后挂载的第一个文件系统。它包含了系统启动所需的目录结构、基本命令、配置文件和库文件,为用户空间程序提供运行环境。 **关键特性**: - Linux 内核初始化时首先挂载的文件系统 - 包含 `/sbin/init` 或指定的 init 程序 - 提供用户空间与内核空间的接口 - 如果没有根文件系统,内核会报 "Kernel panic" 错误 **与普通文件系统的区别**: - 根文件系统在内核启动时自动挂载 - 包含系统启动必需的初始化脚本(如 rcS、inittab) - 通常比普通文件系统更精简 ### 1.2 目录结构 Linux 根文件系统采用标准的目录结构,每个目录有特定用途: | 目录 | 用途 | 说明 | | ------- | ------------ | ---------------------------------------------------------- | | `/bin` | 基本命令 | 系统启动和运行必需的可执行文件,如 ls、mv、cp | | `/sbin` | 系统命令 | 系统管理命令,如 ifconfig、reboot,通常只有管理员使用 | | `/lib` | 共享库 | 系统库文件,供应用程序动态链接使用 | | `/etc` | 配置文件 | 系统配置文件,如 fstab、inittab、resolv.conf | | `/dev` | 设备文件 | 设备节点文件,如 /dev/ttymxc0(I.MX6ULL 串口0)、/dev/null | | `/proc` | 进程信息 | proc 文件系统挂载点,存储系统运行时信息 | | `/sys` | 内核对象 | sysfs 文件系统挂载点,提供内核数据结构信息 | | `/usr` | 用户程序 | Unix Software Resource,用户空间程序和库 | | `/var` | 可变数据 | 日志、缓存等可改变的数据 | | `/mnt` | 挂载点 | 临时挂载目录,如 /mnt/sdcard、/mnt/usb | | `/tmp` | 临时文件 | 系统重启后清空的临时文件 | | `/root` | root用户目录 | root 用户的家目录 | ### 1.3 文件系统类型 嵌入式 Linux 常用的文件系统类型: **磁盘文件系统**: - **ext2/ext3/ext4**:Linux 原生文件系统,支持日志(ext3/ext4) - **FAT32/exFAT**:Windows 兼容,SD 卡常用 - **NTFS**:Windows NT 文件系统 **闪存文件系统**: - **YAFFS/YAFFS2**:专为 NAND Flash 设计 - **UBIFS**:Unsorted Block Image,适用于大容量 NAND - **JFFS2**:Journaling Flash File System **内存文件系统**: - **proc**:进程信息,虚拟文件系统 - **sysfs**:内核对象,虚拟文件系统 - **tmpfs**:临时文件系统,基于内存 **网络文件系统**: - **NFS**:Network File System,开发调试常用 ### 1.4 根文件系统构建流程 ``` 1. 下载并编译 BusyBox(提供基本命令) 2. 创建根文件系统目录结构 3. 拷贝 C 库文件(libc、libm 等) 4. 创建必要的设备节点 5. 编写启动脚本(rcS、inittab 等) 6. 测试与调试 ``` ## 二、BusyBox 构建 ### 2.1 BusyBox 概述 BusyBox 是一个集成了大量 Linux 命令和工具的单个可执行文件。它将 ls、mv、cp、ifconfig 等常用命令集成到一个程序中,大大减小了根文件系统的体积。 **名称由来**:"Busy"(繁忙)+ "Box"(盒子),意为"繁忙的盒子",因为它提供了文件系统所需的大量工具。 **官网**:https://busybox.net/ **优势**: - 体积小:一个可执行文件包含上百个命令 - 配置灵活:可通过 menuconfig 选择需要的功能 - 开源免费:遵循 GPL 协议 - 广泛使用:几乎所有嵌入式 Linux 系统都使用 BusyBox ### 2.2 下载与解压 ```bash # 下载 BusyBox 源码(推荐使用 1.29.0 版本,稳定无 bug) wget https://busybox.net/downloads/busybox-1.29.0.tar.bz2 # 解压源码 tar -vxjf busybox-1.29.0.tar.bz2 # 进入源码目录 cd busybox-1.29.0 ``` > ⚠️ **注意**:建议使用 1.29.0 版本,该版本经过充分测试,稳定性好。 ### 2.3 修改 Makefile 与 Uboot 和 Linux 内核类似,BusyBox 的编译需要指定交叉编译器。修改 `Makefile`: ```makefile # 第 164 行左右 CROSS_COMPILE ?= /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- # 第 190 行左右 ARCH ?= arm ``` **说明**: - `CROSS_COMPILE`:交叉编译器前缀路径(使用绝对路径防止出错) - `ARCH`:目标架构,ARM 芯片设置为 `arm` ### 2.4 中文字符支持修改 默认编译的 BusyBox 在终端中无法正确显示中文字符(显示为 `?`)。需要修改源码: **修改文件 1**:`busybox-1.29.0/libbb/printable_string.c` 找到 `printable_string` 函数,注释掉第 31-32 行和第 45-46 行: ```c // 修改前(第 31-32 行) if (c >= 0x7f) break; // 修改后 /* if (c >= 0x7f) break; */ // 修改前(第 45-46 行) if (c < ' ' || c >= 0x7f) *d = '?'; // 修改后 if( c < ' ') *d = '?'; ``` **修改文件 2**:`busybox-1.29.0/libbb/unicode.c` 找到 `unicode_conv_to_printable2` 函数,修改第 1022 行和第 1030-1031 行: ```c // 修改前(第 1022 行) *d++ = (c >= ' ' && c < 0x7f) ? c : '?'; // 修改后 *d++ = (c >= ' ') ? c : '?'; // 修改前(第 1030-1031 行) if (c < ' ' || c >= 0x7f) *d = '?'; // 修改后 if(c < ' ') *d = '?'; ``` **修改原理**:BusyBox 默认会过滤掉 ASCII 码大于 0x7f 的字符(即中文字符),通过注释掉这些判断,可以使 BusyBox 正确显示中文。 ### 2.5 配置 BusyBox BusyBox 支持三种配置方式: ```bash # 1. 默认配置(推荐初学者) make defconfig # 2. 全选配置(包含所有功能) make allyesconfig # 3. 最小配置(只包含最基本功能) make allnoconfig ``` **图形化配置**(推荐): ```bash make menuconfig ``` **关键配置选项**: **1. 静态编译 vs 动态编译**: ``` Location: -> Settings -> Build static binary (no shared libs) ``` > ⚠️ **重要**:不要选择静态编译!静态编译会导致 DNS 解析失败,无法正常联网。必须使用动态编译。 **2. vi 风格行编辑**: ``` Location: -> Settings -> vi-style line editing commands ``` **3. 简化 modutils**(取消选择): ``` Location: -> Linux Module Utilities -> Simplified modutils ``` **4. 启用 mdev**(确保选中): ``` Location: -> Linux System Utilities -> mdev (16 kb) ``` **5. 启用 Unicode 支持**(可选): ``` Location: -> Settings -> Support Unicode [Y] -> Check $LC_ALL, $LC_CTYPE and $LANG environment variables [Y] ``` ### 2.6 编译与安装 ```bash # 编译 BusyBox make # 安装到指定目录 make install CONFIG_PREFIX=/home/zuozhongkai/linux/nfs/rootfs ``` **CONFIG_PREFIX** 指定安装目录,即根文件系统所在路径。 安装完成后,rootfs 目录结构如下: ``` rootfs/ ├── bin/ # BusyBox 命令链接 ├── sbin/ # 系统命令链接 ├── usr/ # 用户程序 │ ├── bin/ │ └── sbin/ └── linuxrc # init 程序(由 BusyBox 生成) ``` ### 2.7 BusyBox 命令说明 BusyBox 支持的命令可以分为几类: | 类别 | 命令示例 | 说明 | | -------- | --------------------- | -------------- | | 文件操作 | ls, cp, mv, rm, mkdir | 基本文件管理 | | 文本处理 | cat, grep, sed, awk | 文本查看和处理 | | 网络工具 | ifconfig, ping, wget | 网络配置和测试 | | 系统管理 | ps, kill, top, free | 进程和系统管理 | | 存储工具 | mount, fdisk, df | 存储设备管理 | ## 三、根文件系统目录创建 ### 3.1 创建基本目录结构 在 rootfs 目录下创建必要的目录: ```bash cd rootfs # 创建基本目录 mkdir -p bin sbin lib etc usr dev proc sys tmp mnt root # 创建 usr 子目录 mkdir -p usr/bin usr/sbin usr/lib # 创建 dev 子目录(用于 mdev) mkdir -p dev/pts ``` ### 3.2 创建设备节点 > ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识。书中第三十八章通过`mdev -s`自动创建设备节点,并未手动`mknod`。 Linux 系统需要基本的设备节点才能正常运行: ```bash cd dev # 控制台设备 sudo mknod console c 5 1 # 空设备 sudo mknod null c 1 3 # 终端设备 sudo mknod ttymxc0 c 4 64 # 随机数设备 sudo mknod random c 1 8 # _urandom 设备 sudo mknod urandom c 1 9 cd .. ``` **设备号说明**: - 第一个数字:设备类型(c=字符设备,b=块设备) - 第二个数字:主设备号 - 第三个数字:次设备号 ### 3.3 /etc 目录配置 > ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识。书中第三十八章只创建了`/etc/init.d/rcS`、`/etc/fstab`、`/etc/inittab`和`/etc/resolv.conf`,未创建`/etc/passwd`、`/etc/group`、`/etc/profile`。 `/etc` 目录包含系统配置文件,是根文件系统中最关键的目录之一。 **创建 /etc/passwd 文件**: ```bash # 用户信息文件 cat > etc/passwd << 'EOF' root::0:0:root:/root:/bin/sh EOF ``` **创建 /etc/group 文件**: ```bash # 用户组信息文件 cat > etc/group << 'EOF' root:x:0: EOF ``` **创建 /etc/profile 文件**: ```bash cat > etc/profile << 'EOF' export PATH=/sbin:/bin:/usr/sbin:/usr/bin export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib export runlevel=S export umask=022 EOF ``` ### 3.4 /etc/init.d/rcS 文件 `rcS` 是系统启动后执行的第一个脚本,用于初始化系统: ```bash cat > etc/init.d/rcS << 'EOF' #!/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib export PATH LD_LIBRARY_PATH mount -a mkdir /dev/pts mount -t devpts devpts /dev/pts echo /sbin/mdev > /proc/sys/kernel/hotplug mdev -s EOF chmod 777 etc/init.d/rcS ``` **脚本说明**: - 第 1 行:指定 shell 解释器 - 第 3-5 行:设置环境变量(PATH 和库路径) - 第 7 行:挂载 /etc/fstab 中定义的所有文件系统 - 第 8-9 行:创建并挂载 devpts 文件系统(用于伪终端) - 第 11-12 行:启用 mdev 热插拔支持 ### 3.5 /etc/fstab 文件 `fstab` 文件定义了需要自动挂载的文件系统: ```bash cat > etc/fstab << 'EOF' # proc /proc proc defaults 0 0 tmpfs /tmp tmpfs defaults 0 0 sysfs /sys sysfs defaults 0 0 EOF ``` **字段说明**: - ``:要挂载的设备或文件系统 - ``:挂载点 - ``:文件系统类型 - ``:挂载选项(defaults 表示使用默认选项) - ``:是否备份(0=不备份) - ``:开机时是否检查(0=不检查) ### 3.6 /etc/inittab 文件 `inittab` 文件定义了 init 进程的行为: ```bash cat > etc/inittab << 'EOF' #etc/inittab ::sysinit:/etc/init.d/rcS console::askfirst:-/bin/sh ::restart:/sbin/init ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r ::shutdown:/sbin/swapoff -a EOF ``` **字段格式**:`:::` **action 类型说明**: | action | 说明 | | ---------- | ------------------------------------------------------------------ | | sysinit | 系统初始化,执行一次 | | respawn | 进程终止后重新启动 | | askfirst | 显示 "Please press Enter to activate this console",等待用户按回车 | | wait | 等待进程执行完毕 | | once | 执行一次,不等待 | | restart | init 重启时执行 | | ctrlaltdel | 按 Ctrl+Alt+Del 时执行 | | shutdown | 关机时执行 | ## 四、库文件拷贝 ### 4.1 C 库选择 嵌入式 Linux 系统需要 C 库来支持动态链接的程序。常用的 C 库有: - **glibc**:GNU C Library,功能完整,体积较大 - **uClibc**:专为嵌入式设计,体积小 - **musl**:轻量级 C 库,兼容性好 I.MX6ULL 开发板使用 Linaro 工具链,对应的 C 库位于: ``` /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib ``` ### 4.2 拷贝 /lib 库文件 ```bash # 进入库文件目录 cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib # 拷贝所有动态库和静态库到 rootfs/lib cp *so* *.a /home/zuozhongkai/linux/nfs/rootfs/lib/ -d ``` **重要:修复 ld-linux-armhf.so.3 链接** `ld-linux-armhf.so.3` 是动态链接器,必须是实际文件而非符号链接: ```bash # 删除 rootfs/lib 中的符号链接 rm ld-linux-armhf.so.3 # 从工具链目录拷贝实际文件(注意:不带 -d,复制出的是实体文件) cp /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/ld-linux-armhf.so.3 /home/zuozhongkai/linux/nfs/rootfs/lib/ ``` 再进入工具链的 `.../arm-linux-gnueabihf/lib` 目录,把里面的库也拷进 `rootfs/lib`: ```bash cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib cp *so* *.a /home/zuozhongkai/linux/nfs/rootfs/lib/ -d ``` ### 4.3 拷贝 /usr/lib 库文件 ```bash # 进入 usr/lib 库文件目录 cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib # 拷贝所有库文件到 rootfs/usr/lib cp *so* *.a /home/zuozhongkai/linux/nfs/rootfs/usr/lib/ -d ``` ### 4.4 验证库文件 ```bash # 查看库文件大小 cd rootfs du ./lib ./usr/lib/ -sh # 示例输出: # 57M ./lib # 67M ./usr/lib ``` > 💡 **提示**:库文件总大小约 124MB,对于 256MB/512MB NAND Flash 的开发板可能空间不足,建议使用 EMMC 版本。 ## 五、完整构建脚本 ### 5.1 一键构建脚本 > ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识。书中第三十八章给出的是手动分步操作,未提供该一键脚本。 ```bash #!/bin/bash # rootfs_build.sh - 一键构建根文件系统 # 配置参数 TOOLCHAIN_DIR=/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf ROOTFS_DIR=/home/zuozhongkai/linux/nfs/rootfs BUSYBOX_VERSION=1.29.0 # 1. 创建 rootfs 目录 echo "1. 创建 rootfs 目录..." mkdir -p $ROOTFS_DIR # 2. 解压并编译 BusyBox echo "2. 编译 BusyBox..." tar -vxjf busybox-${BUSYBOX_VERSION}.tar.bz2 cd busybox-${BUSYBOX_VERSION} # 修改 Makefile sed -i "s|^CROSS_COMPILE ?=.*|CROSS_COMPILE ?= ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-|" Makefile sed -i "s|^ARCH ?=.*|ARCH ?= arm|" Makefile # 配置并编译 make defconfig make -j$(nproc) make install CONFIG_PREFIX=$ROOTFS_DIR cd .. # 3. 创建目录结构 echo "3. 创建目录结构..." cd $ROOTFS_DIR mkdir -p bin sbin lib etc usr dev proc sys tmp mnt root mkdir -p usr/bin usr/sbin usr/lib dev/pts # 4. 创建设备节点 echo "4. 创建设备节点..." cd dev sudo mknod console c 5 1 sudo mknod null c 1 3 sudo mknod ttymxc0 c 4 64 sudo mknod random c 1 8 sudo mknod urandom c 1 9 cd .. # 5. 拷贝库文件 echo "5. 拷贝库文件..." cp ${TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc/lib/*so* ${TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc/lib/*.a $ROOTFS_DIR/lib/ -d cp ${TOOLCHAIN_DIR}/arm-linux-gnueabihf/lib/*so* ${TOOLCHAIN_DIR}/arm-linux-gnueabihf/lib/*.a $ROOTFS_DIR/lib/ -d cp ${TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc/usr/lib/*so* ${TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc/usr/lib/*.a $ROOTFS_DIR/usr/lib/ -d # 修复 ld-linux-armhf.so.3 rm -f $ROOTFS_DIR/lib/ld-linux-armhf.so.3 cp ${TOOLCHAIN_DIR}/arm-linux-gnueabihf/libc/lib/ld-linux-armhf.so.3 $ROOTFS_DIR/lib/ # 6. 创建配置文件 echo "6. 创建配置文件..." # /etc/passwd cat > etc/passwd << 'EOF' root::0:0:root:/root:/bin/sh EOF # /etc/group cat > etc/group << 'EOF' root:x:0: EOF # /etc/profile cat > etc/profile << 'EOF' export PATH=/sbin:/bin:/usr/sbin:/usr/bin export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib export runlevel=S export umask=022 EOF # /etc/init.d/rcS mkdir -p etc/init.d cat > etc/init.d/rcS << 'EOF' #!/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib export PATH LD_LIBRARY_PATH mount -a mkdir /dev/pts mount -t devpts devpts /dev/pts echo /sbin/mdev > /proc/sys/kernel/hotplug mdev -s EOF chmod 777 etc/init.d/rcS # /etc/fstab cat > etc/fstab << 'EOF' # proc /proc proc defaults 0 0 tmpfs /tmp tmpfs defaults 0 0 sysfs /sys sysfs defaults 0 0 EOF # /etc/inittab cat > etc/inittab << 'EOF' #etc/inittab ::sysinit:/etc/init.d/rcS console::askfirst:-/bin/sh ::restart:/sbin/init ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r ::shutdown:/sbin/swapoff -a EOF # /etc/resolv.conf(DNS 配置) cat > etc/resolv.conf << 'EOF' nameserver 114.114.114.114 nameserver 192.168.1.1 EOF echo "7. 根文件系统构建完成!" echo " 目录:$ROOTFS_DIR" ``` ### 5.2 脚本使用说明 ```bash # 1. 赋予执行权限 chmod +x rootfs_build.sh # 2. 执行脚本 ./rootfs_build.sh # 3. 验证构建结果 ls -la $ROOTFS_DIR ``` ### 5.3 目录大小检查 ```bash # 查看 rootfs 总大小 du -sh $ROOTFS_DIR # 查看各目录大小 du -sh $ROOTFS_DIR/* ``` ## 六、根文件系统测试 ### 6.1 NFS 测试 NFS(Network File System)是开发阶段最常用的测试方式,无需烧写到 Flash。 **配置 Uboot 环境变量**: ```bash # 在 Uboot 命令行执行 setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.250:/home/zuozhongkai/linux/nfs/rootfs,proto=tcp rw ip=192.168.1.251:192.168.1.250:192.168.1.1:255.255.255.0::eth0:off' saveenv boot ``` **NFS 挂载参数说明**: | 参数 | 说明 | 示例值 | | --------------------------------------------------- | -------------------- | ------------------------------ | | `root=/dev/nfs` | 指定 NFS 根文件系统 | - | | `nfsroot=:` | NFS 服务器 IP 和路径 | 192.168.1.250:/home/.../rootfs | | `proto=tcp` | 使用 TCP 协议 | - | | `rw` | 读写权限 | - | | `ip=::::::off` | 网络配置 | 192.168.1.251:... | ### 6.2 启动测试 系统启动后,应该能够进入 shell 环境: ``` Please press Enter to activate this console. # ls bin dev etc lib linuxrc mnt proc root sbin sys tmp usr # ``` ### 6.3 功能测试 **1. 测试动态链接程序**: ```bash # 在 Ubuntu 上编译测试程序 arm-linux-gnueabihf-gcc hello.c -o hello # 拷贝到 rootfs/drivers 目录 cp hello $ROOTFS_DIR/drivers/ # 在开发板上运行 cd /drivers ./hello ``` **2. 测试中文字符显示**: ```bash # 创建中文测试文件 mkdir 测试目录 touch 测试文档.txt echo "你好世界" > 测试文档.txt # 验证显示 ls cat 测试文档.txt ``` **3. 测试网络功能**: ```bash # 配置 IP 地址 ifconfig eth0 192.168.1.251 # 测试 ping ping www.baidu.com ``` ### 6.4 开机自启动 在`/etc/init.d/rcS`末尾加上自启动命令即可让程序随系统启动(书中 38.5.3): ```bash #!/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib runlevel=S umask 022 export PATH LD_LIBRARY_PATH runlevel mount -a mkdir /dev/pts mount -t devpts devpts /dev/pts echo /sbin/mdev > /proc/sys/kernel/hotplug mdev -s # 开机自启动 cd /drivers ./hello & cd / ``` ### 6.5 常见问题排查 **问题 1:can't run '/etc/init.d/rcS': No such file or directory** - 原因:rcS 文件不存在或没有执行权限 - 解决:创建 rcS 文件并执行 `chmod 777 /etc/init.d/rcS` **问题 2:中文字符显示为 '?'** - 原因:BusyBox 未修改中文支持 - 解决:重新编译 BusyBox,修改 `printable_string.c` 和 `unicode.c` **问题 3:ping 显示 "bad address"** - 原因:DNS 配置缺失 - 解决:创建 `/etc/resolv.conf` 文件,配置 DNS 服务器 **问题 4:动态链接程序无法运行** - 原因:缺少动态链接器 `ld-linux-armhf.so.3` - 解决:确保拷贝的是实际文件而非符号链接 ## 七、跨平台对比 > ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识。 ### 7.1 IMX6ULL vs STM32 vs RK3568 根文件系统差异 | 特性 | I.MX6ULL | STM32MP1 | RK3568 | | ---------------- | -------------------- | ------------------------------ | ------------------ | | **架构** | ARM Cortex-A7 | ARM Cortex-A7 | ARM Cortex-A55 | | **位宽** | 32-bit | 32-bit | 64-bit | | **交叉编译器** | arm-linux-gnueabihf- | arm-openstlinux-linux-gnueabi- | aarch64-linux-gnu- | | **C 库** | glibc | glibc | glibc | | **文件系统类型** | ext4/squashfs | ext4 | ext4/squashfs | | **推荐构建工具** | BusyBox/Buildroot | Yocto/Buildroot | Buildroot/Debian | | **根 FS 大小** | 50-200MB | 100-500MB | 200MB-2GB | ### 7.2 构建工具对比 | 工具 | 特点 | 适用场景 | | ------------- | ---------------------- | -------------- | | **BusyBox** | 手动构建,完全控制 | 学习、小型系统 | | **Buildroot** | 自动化构建,配置简单 | 中小型项目 | | **Yocto** | 功能强大,学习曲线陡峭 | 大型商业项目 | | **Debian** | 完整 Linux 发行版 | 需要丰富软件包 | ### 7.3 文件系统大小优化 | 优化方法 | 效果 | 说明 | | ------------------------- | ----------- | ------------------ | | 使用 BusyBox 替代完整工具 | 减小 50-70% | BusyBox 集成多命令 | | 使用 squashfs 压缩 | 减小 50-60% | 只读压缩文件系统 | | 去除未使用的库 | 减小 20-40% | 精简 C 库 | | 使用 uClibc 替代 glibc | 减小 30-50% | 更小的 C 库 | ## 八、面试精选 > ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识(答案基于书中事实整理)。 ### 题目 1:什么是根文件系统?它与普通文件系统有什么区别? **考察点**:基础概念理解 **参考答案**: 根文件系统(rootfs)是 Linux 内核启动时挂载的第一个文件系统,包含系统启动必需的目录结构、命令、库文件和配置文件。 **与普通文件系统的区别**: 1. **挂载时机**:rootfs 在内核初始化时自动挂载,普通文件系统需要手动或自动挂载 2. **内容要求**:rootfs 必须包含 init 程序和基本命令,普通文件系统无此要求 3. **完整性**:rootfs 是系统运行的基础,缺失会导致 kernel panic 4. **特殊目录**:rootfs 包含 /proc、/sys、/dev 等特殊目录 ### 题目 2:BusyBox 的作用是什么?为什么嵌入式系统常用 BusyBox? **考察点**:工具理解 **参考答案**: BusyBox 是一个集成了大量 Linux 命令和工具的单个可执行文件,被称为"嵌入式 Linux 的瑞士军刀"。 **常用原因**: 1. **体积小**:一个可执行文件包含上百个命令,大大减小根文件系统体积 2. **配置灵活**:通过 menuconfig 可以选择需要的功能,按需定制 3. **性能优化**:针对嵌入式系统优化,启动速度快 4. **开源免费**:遵循 GPL 协议,无授权费用 5. **广泛支持**:几乎所有嵌入式 Linux 发行版都支持 BusyBox ### 题目 3:根文件系统构建过程中,为什么需要修改 BusyBox 源码来支持中文? **考察点**:实际问题解决 **参考答案**: BusyBox 默认会过滤 ASCII 码大于 0x7f 的字符(即非 ASCII 字符),导致中文字符显示为 `?`。 **修改原理**: 1. `printable_string.c` 中的 `printable_string` 函数会将 >= 0x7f 的字符替换为 `?` 2. `unicode.c` 中的 `unicode_conv_to_printable2` 函数也有类似逻辑 3. 通过注释掉这些判断,可以保留中文字符的原始编码 **修改后的效果**: - 终端可以正确显示中文文件名和目录名 - 支持中文文本编辑和查看 - 提升用户体验 ### 题目 4:在构建根文件系统时,为什么不能选择 BusyBox 的静态编译? **考察点**:配置选项理解 **参考答案**: 静态编译会将所有库函数直接链接到可执行文件中,虽然简化了依赖,但会导致严重问题: **DNS 解析失败**: - 静态链接的程序无法使用系统的动态 DNS 解析器 - 导致 `ping www.baidu.com` 等网络命令失败 **体积增大**: - 静态链接的程序体积比动态链接大 5-10 倍 - 浪费宝贵的存储空间 **内存占用**: - 每个静态程序都包含完整的库代码 - 多个程序运行时内存占用成倍增加 **最佳实践**:使用动态编译,确保 `/lib` 目录包含必要的动态库。 ### 题目 5:如何让根文件系统支持自动挂载 USB 设备和 SD 卡? **考察点**:系统配置能力 **参考答案**: 需要配置 mdev 和相应的挂载点: **1. 确保 mdev 配置正确**: ```bash # /etc/init.d/rcS echo /sbin/mdev > /proc/sys/kernel/hotplug mdev -s ``` **2. 创建挂载点**: ```bash mkdir -p /mnt/usb /mnt/sdcard ``` **3. 配置 mdev 规则**(可选): ```bash # /etc/mdev.conf sd[a-z][0-9]* 0:0 0660 */bin/mount /dev/$MDEV /mnt/sdcard sd[a-z] 0:0 0660 */bin/umount /mnt/sdcard ``` **4. 配置 fstab**(可选): ```bash # /etc/fstab /dev/sda1 /mnt/usb vfat defaults 0 0 /dev/mmcblk0p1 /mnt/sdcard vfat defaults 0 0 ``` **验证方法**: 1. 插入 USB 设备或 SD 卡 2. 执行 `ls /mnt/usb` 或 `ls /mnt/sdcard` 3. 检查设备是否自动挂载 --- **内容来源**: 《I.MX6U嵌入式Linux驱动开发指南》第38章 根文件系统构建 **最后更新**: 2026-09-17