Linux 的缩骨功——openwrt 与其文件系统的原理探究

本文来自于我近年来折腾 openwrt 系统一大串疑问及探索过程收集整理。从约 2015 年开始买了 HG255D 刷 openwrt 入坑之后,openwrt 带给我疑问与答案探索的心路历程包括:

  • openwrt 竟然和 dd-wrt,tomato 等第三方固件差别这么大,自由度这么高,好 Linuxy 啊!
  • 为路由器刷 openwrt 需要 “不死 uboot”,只要 uboot 尚存,刷什么固件都可以,这不就是 PC 的 BIOS 或 UEFI,有个 U 盘就能装系统呀!
  • 刷了 openwrt 以后,因为要装的软件很多(尤其是越来越多的 go 写就的软件),路由器厂家为了成本节省而内置的存储空间不够,因此带 USB 接口可插 U 盘的路由器拥有了上 GB 额外存储空间的机会,不过为什么要挂载成软件安装的地方,这么复杂?…

到了 2024 年,当一批联发科 filogic 芯片带动的、能刷 openwrt 的 WiFi6 路由器兴起后,通过不断的踩坑、填坑、折腾,终于对脱胎于 Linux 但又因嵌入式的桎梏而做出相当多改造的 openwrt 及其文件系统有了更深层的一些认知。

以 AI 为师,是当下最流行的一件事。在踩坑的过程中,通过告诉 AI“我不要操作过程我要知道原理”,问出我最好奇的事:x86 Linux 的文件系统以 / 为根目录,以 openwrt 为代表的嵌入式 Linux 系统,在一块成本低廉的闪存芯片上为什么有着着复杂的 “分区”:uboot 、只读 SquashFS 、 overlay 、 JFFS?

Google gemini 解答如下:

[ U-Boot ]路由器通电后最先执行
[ U-Boot Env/Config ]U-Boot 的配置参数
[ Linux Kernel ]U-Boot 加载并运行它
[ SquashFS (只读 rom) ]系统的核心,出厂固件就固定在这里
[ JFFS2/UBIFS (可写 /overlay) ]你所有的更改、安装的软件都写入这里 (默认情况下)
[ 其他分区 (如日志, 恢复等) ]optional
「你可以想象路由器闪存芯片被逻辑上划分成上面这样(具体名称和大小会因路由器型号而异)

第一,位于内置存储最前端的、类似于 UEFI 的、负责引导操作系统的 bootloader 是必不可少的。磕碜一点的 bootloader 带 tftp 加载功能,须刷机的 PC 端以 tftp 协议传入固件;豪华一点的 bootloader 带 web GUI 可上传并刷入固件,甚至带简单的 DHCP 以增强用户体验。刷入 openwrt 系统时一般会避开这一部分,如果这一部分也被刷去,那么在拆机 JTAG 介入之前,那可就真的砖了。

第二,和安装在 x86 设备上传统 Linux 系统有着本质不同的是,嵌入式 openwrt 系统必须有种 “RESET 重置” 后,能恢复到某种固定的 “出厂设置” 状态的 feature,不能像安装在 PC 或 server 传统 Linux 那样 “格盘” 后只剩空荡荡的硬盘。因此一个 “只读” 的文件系统、在 “RESET 重置” 后能恢复到一个固定状态(譬如默认网段为 192.168.1.0/24,默认网关 192.168.1.1 这样的出厂默认值)的文件系统是必不可少的。这就是上述的只读 ROM,位于 SquashFS 文件系统的部分。

第三,我们对路由器所做的任何设置,如默认网段、网关、防火墙策略、 WAN 口 PPPoE 账号密码、第三方软件等配置,都会存储在挂载为 /overlay 的 JFFS2/UBIFS 文件系统中(/overlay/etc)。关键在于,这里的 /overlay ,既可以是路由器刷入 openwrt 后的剩余空间,又可以是 USB 外置存储。

我是怎么知道个性化配置都存在 /etc 中的…… openwrt 的配置备份并下载后是个 backup.tar.gz 文件,打开后就知道了……

也就是说,如果未插入外置存储,/overlay 将会是路由器闪存中紧跟着固件之后的一片闪存空间;插入 USB 存储并正确识别、挂载为 /overlay 后,/overlay 就会在外置存储中。

而此时,运行中的 openwrt 的 /etc 是一个动态的、由 OverlayFS 合并生成的虚拟目录/overlay/etc 是一个实际存在于可变存储区(参考上一节,无 U 盘时是路由器闪存的 JFFS2/UBIFS,有 U 盘时是优盘)上的物理目录,专门用来存放你对系统配置所做的所有个性化更改。出厂设定(默认 /etc 内容)则存储于只读的 SquashFS 中,平时被上层(即 Overlay 的字面意思)遮蔽而不生效,只有 RESET 重置后,也就是上层遮蔽都没了的时候,才生效。

这种聪明的办法可以解决固定的出厂设定问题,也可以使我插了 U 盘并用作 /overlay 的路由器有了一个保底方案,即内置的较为紧张的 JFFS2/UBIFS 存储中存一份路由器能正常运作的 “最小配置”,用于日常使用的白菜价 U 盘外置存储则承担日常 /overlay 职能,装了一堆 ipk 软件包。即使在 U 盘本身或挂载出现问题的情况下,也可以 fallback 回落到能满足最基本上网需求的 “最小配置” 。

我常惊叹的 Linux 的 “缩骨功” 厉害之处在于,不仅能像被 “缩小灯” 照过一样装入螺蛳壳般的嵌入式设备存储空间中,还能以 “柔软的身段”——灵活的文件系统、挂载方式去实现 “用户能一键 RESET 恢复出厂设置” 这样的需求。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注