使用overlayfs时切换root后释放initramfs ram?

使用overlayfs时切换root后释放initramfs ram?

我正在构建一个基于 Arch Linux 的自定义 Live Linux 启动映像。我已经修改了 Stock initrd 以包含执行以下操作的自定义脚本:

  • 启动后,只有initramfs存在。我首先找到启动介质并将​​其安装在/image.
  • 然后,我将我的 squashfs 根文件系统环回挂载到/ro.
  • 然后,我安装 tmpfs/rw并在该目录中创建目录datawork
  • 最后,我安装了一个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 中实际可执行文件大小的两倍。rowork/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_roothttp://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应该正确清除根文件系统。

相关内容