我正在构建一个基于 Arch Linux 的自定义 Live Linux 启动映像。我已经修改了 Stock initrd 以包含执行以下操作的自定义脚本:
- 启动后,只有initramfs存在。我首先找到启动介质并将其安装在
/image
. - 然后,我将我的 squashfs 根文件系统环回挂载到
/ro
. - 然后,我安装 tmpfs
/rw
并在该目录中创建目录data
。work
- 最后,我安装了一个overlayfs,用作
/ro
底层、/rw/data
顶层和/rw/work
工作目录。我将这个overlayfs安装在/new_root
. - 我现在习惯
switch_root
切换到/new_root
并继续启动。
这种方法的问题是 initramfs 内容在系统启动后仍然保留在 RAM 中。
有什么方法可以重新处理该过程,以便在切换到真正的根之后,可以从内存中删除 initramfs 吗?这很重要的原因是因为我试图在内存占用较小的机器(192MB)上启动我的实时 Linux,并且 initrd 的大小(我基于 initramfs-fallback)意味着在一切启动后,我只有大约30MB 可用 RAM。相比之下,典型安装的 Arch Linux 将仅使用大约 18MB 的 RAM。这向我表明,解压后的 initramfs(大约 66MB)肯定仍在 RAM 中,还有另外 66MB 左右的 RAM,我无法确定其使用情况。 (也许由于某种原因 initramfs 实际上在 RAM 中是重复的?)
我显然可以缩小我的 initramfs (我正在研究如何指定要包含在包中的特定模块),但即便如此,在低内存系统上启动后仍将使用大量 RAM。
编辑:我尝试重新设计我的 initramfs 以简单地在 上安装一个 tmpfs ,/image
然后rw
脚本在.然后,该脚本执行挂载,然后将 Overlayfs 挂载到 上。结果完全相同 - RAM 使用量大约是 initramfs 大小加上 RAM 中实际可执行文件大小的两倍。ro
work
/image
/new_root
我请求预安装中断,在该阶段,RAM 中仅使用 initramfs 的大小 - 这是有道理的。然后,我请求安装后中断,发现 RAM 使用量是我在启动系统中观察到的两倍。所以看起来各种挂载中的某些东西导致了 RAM 使用。我将尝试通过向 initrd 脚本添加命令来跟踪进程,free
看看sleep
是否可以隔离哪个命令导致内存使用...
再次编辑:所以“双倍”RAM 使用的罪魁祸首是 SquashFS。因此,看起来我应该使用 gzip 而不是使用 lzma 重新压缩文件系统。好吧,部分谜团解开了。
但这仍然无法解决 root 切换后 initramfs 继续使用 RAM 的问题。所以这仍然是一个谜。
我想知道内核是否尝试在内部卸载 initramfs 但无法这样做,因为上面安装了一些东西?但这没有意义,因为你会总是无论如何,在切换 root 之前,先从 initramfs 安装一些东西......
答案1
我假设您指的是“rootfs”。不,没有办法摆脱它。内核文档甚至特别提到了这一点:https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt
Rootfs 是 ramfs(或 tmpfs,如果启用的话)的一个特殊实例,它始终存在于 2.6 系统中。您无法卸载 rootfs 的原因与您无法终止 init 进程的原因大致相同;内核不必使用特殊的代码来检查和处理空列表,而是更小、更简单地确保某些列表不会变空。
大多数系统只是在 rootfs 上挂载另一个文件系统并忽略它。 ramfs 的空实例占用的空间量很小。
您也无需担心清理问题rootfs
。请参阅文档switch_root
:http://man7.org/linux/man-pages/man8/switch_root.8.html
警告:switch_root 会递归删除当前根文件系统上的所有文件和目录。
另外,回到内核文档,在引用的“rootfs”文档下方是另一个简介,它重申了上述两点:
当切换另一个根设备时,initrd 会pivot_root,然后卸载ramdisk。但 initramfs 是 rootfs:您既不能使用ivot_root rootfs,也不能卸载它。相反,删除 rootfs 中的所有内容以释放空间(find -xdev / -exec rm '{}' ';'),使用新根覆盖 rootfs(cd /newmount; mount --move . /; chroot .),将 stdin/stdout/stderr 连接到新的 /dev/console,并执行新的 init。
由于这是一个非常挑剔的过程(并且涉及在运行命令之前删除命令),因此 klibc 包引入了一个帮助程序(utils/run_init.c)来为您完成所有这些工作。大多数其他软件包(例如 busybox)已将此命令命名为“switch_root”。
答案2
因此,无论出于何种原因,问题似乎是如果您安装任何事物在 initramfs 上,除了 at/new_root
或预安装的任何其他东西之外,initramfs 不会从内存中清除。不知道为什么会这样。
所以我查看了 Arch Linux 启动 ISO 上的脚本,发现它基本上做了与我的想法类似的事情,但它在/run
.由于/run
首先是 tmpfs,所以无论如何这最终都会节省一些步骤。
通过调整我的脚本来执行相同的操作,我最终能够创建一个在 128MB RAM 中启动的 ISO,并为应用程序留下 80MB 的可用 RAM。不错。
所以诀窍是在 /run 下挂载您需要挂载的任何内容,然后switch_root
应该正确清除根文件系统。