Skip to content

[Feature] 内核自动下载逻辑对资源受限环境考虑不足 #1304

Description

@ashi009

Verify steps

Description

下载哪种产物、解压到哪里(zip_type / core_unzip),现在只看压缩包大小。OpenWrt 上有两件事没被考虑:

  1. $TMPDIR 在 tmpfs 上,解压出来的内核直接占 RAM,计入 Shmem,不可回收;
  2. overlayfs 底下的 ubifs/squashfs 透明压缩,裸二进制存进去并不占那么多闪存。

结果是压缩得越狠,运行时占的内存越多。同一个内核(bin/meta/clash-linux-arm64.upx.tar.gz 里的是同一个 aarch64 构建,30277758 字节),三种存法:

存法 闪存实占 不可回收内存
.upx 9.08 MB ≥ 28.88 MB,且更差,见下
.tar.gz 解压到 $TMPDIR 10.56 MB 28.88 MB(tmpfs)
裸二进制放 $BINDIR 13.09 MB 0

闪存一列在 ubifs 上实测。压缩包压不动(.tar.gz 1.02:1),裸二进制 2.21:1,所以裸二进制只比 .tar.gz 多占 2.5 MB。

.upx 最亏。UPX 的 stub 在 exec 时 memfd_create 把整个程序解压回内存(/proc/PID/maps 里的 /memfd:upx),memfd 本身就是 tmpfs,一样算 Shmem;rodata/data 还从共享文件映射变成了私有匿名页。换成 upx 内核后实测 MemAvailable 少了约 19 MB。

复现

# 改造前:内核解压在 /tmp/ShellCrash/CrashCore
$ grep -E '^(MemAvailable|Shmem):' /proc/meminfo
MemAvailable:      39900 kB
Shmem:             45128 kB
$ grep -E '^Rss' /proc/$(pidof CrashCore)/status
RssAnon:	   41856 kB
RssFile:	     176 kB
RssShmem:	   36876 kB

# 让内核留在 $BINDIR 上执行。借用 core_unzip 对 .upx 只软链不解压的分支,
# 但文件其实是未压缩的裸二进制。
$ /etc/init.d/shellcrash stop
$ gzip -dc /etc/ShellCrash/CrashCore.gz > /etc/ShellCrash/CrashCore.upx
$ chmod +x /etc/ShellCrash/CrashCore.upx
$ rm -f /etc/ShellCrash/CrashCore.gz /tmp/ShellCrash/CrashCore
$ /etc/init.d/shellcrash start

# 改造后
$ grep -E '^(MemAvailable|Shmem):' /proc/meminfo
MemAvailable:      75724 kB
Shmem:               980 kB
$ grep -E '^Rss' /proc/$(pidof CrashCore)/status
RssAnon:	   28456 kB
RssFile:	   36096 kB
RssShmem:	       0 kB

RssShmem 归零,RssFile 接手 —— 代码段和 rodata 变成 file-backed、按需分页、内核可回收。/tmp 占用从 45.1 MB 降到 2.0 MB。

修复方案

不必新增下载格式 —— 照常下载 .tar.gz/.gz(里面本就是裸二进制)。变的是存储策略,由文件系统条件决定:

  • $TMPDIR 是 tmpfs(RAM) $BINDIR 在透明压缩的 fs(squashfs / ubifs / overlay-over-them)上时:把校验好的裸二进制留在 $BINDIR$TMPDIR/CrashCore 软链过去,不解压到 tmp、也不保留下载的压缩包
  • 否则维持现状(rom 上留压缩件,启动时解压到 tmp)。

现状对这类设备是双重浪费:rom 上留一份压缩 CrashCore.gz,每次启动又解压整份到 tmpfs 常驻。而 ubifs 本身透明压缩,裸二进制存进去(约 2.2:1)和留 .gz 闪存占用相当,却省下整份 RAM。.raw 只是落盘形态,不是下载格式 —— 下载仍走 .tar.gz/.gzcore_findCrashCore.* glob 配合 core_unzip.raw 分支在启动时重建软链。

已提交 #1305 实现,并在真实 fs 上验证三条路径:压缩 rom 存 raw;重启 core_find 重建软链、运行时 RssShmem 归零;非压缩 rom 回退旧行为。顺带修正了 upx 分支软链目标 $TMPDIR$BINDIR(与 #1295 同一处悬空 bug)。

环境:ImmortalWrt 25.12,ShellCrash 1.9.5alpha14,aarch64。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions