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

fdm*_*ion 7 livecd initramfs

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

  • 启动后,只有 initramfs 存在。我首先在/image.
  • 然后,我在/ro.
  • 然后,我挂载 tmpfs并在该目录中/rw创建目录。datawork
  • 最后,我使用/ro作为底层、/rw/data顶层和/rw/work工作目录安装了一个overlayfs 。我在/new_root.
  • 我现在使用switch_root切换到/new_root并继续启动。

这种方法的问题在于,initramfs 内容在系统启动后仍会很好地保留在 RAM 中。

有什么办法可以重新处理这个过程,以便在切换到真正的根目录后,可以从内存中删除 initramfs?这很重要的原因是因为我试图在一个小内存占用机器 (192MB) 上启动我的实时 Linux 并且 initrd 的大小(我基于 initramfs-fallback)意味着在一切都启动后,我只有大约30MB 可用内存。相比之下,典型安装的 Arch Linux 将仅使用大约 18MB 的 RAM。这向我表明解压后的 initramfs(大约 66MB)肯定仍在 RAM 中,还有另外 66MB 左右的 RAM,我无法从中弄清楚使用情况。(也许出于某种原因,initramfs 实际上在 RAM 中是重复的?)

我显然可以缩小我的 initramfs(我正在研究如何指定要包含在包中的特定模块),但即便如此,在低内存系统上启动后仍将使用大量 RAM。


编辑:我想我返工initramfs中简单地安装上一个tmpfs的/image,然后该脚本创建rwro以及work内部目录/image。然后,脚本执行挂载,然后将 overlayfs 挂载到/new_root. 结果完全相同——RAM 使用量大约是 initramfs 加上 RAM 中实际可执行文件大小的两倍。

我请求预先安装中断,在那个阶段,RAM 中只使用了 initramfs 的大小 - 这是有道理的。然后我请求安装后中断,发现 RAM 使用量是我在启动系统中观察到的两倍。所以看起来各种安装中的某些东西导致了RAM使用。我将尝试通过向initrd 脚本添加freesleep命令来跟踪进程,以查看是否可以隔离哪个命令导致内存使用...


再次编辑:所以“双倍”RAM 使用的罪魁祸首是 SquashFS。因此,看起来我应该使用 gzip 而不是 lzma 重新压缩文件系统。好的,部分谜团解开了。

但这仍然没有处理切换 root 后 initramfs 继续使用 RAM 的问题。所以这仍然是个谜。

我想知道内核是否会尝试在内部卸载 initramfs 但无法这样做,因为上面安装了一些东西?但这没有意义,因为在您切换 root 之前,您总是会从 initramfs 挂载一些东西......

phe*_*mer 2

我假设您指的是“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”。