我正在构建一个基于 Arch Linux 的自定义 Live Linux 启动映像。我修改了股票 initrd 以包含一个自定义脚本,它执行以下操作:
/image
./ro
./rw
创建目录。data
work
/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
,然后该脚本创建rw
,ro
以及work
内部目录/image
。然后,脚本执行挂载,然后将 overlayfs 挂载到/new_root
. 结果完全相同——RAM 使用量大约是 initramfs 加上 RAM 中实际可执行文件大小的两倍。
我请求预先安装中断,在那个阶段,RAM 中只使用了 initramfs 的大小 - 这是有道理的。然后我请求安装后中断,发现 RAM 使用量是我在启动系统中观察到的两倍。所以看起来各种安装中的某些东西导致了RAM使用。我将尝试通过向initrd 脚本添加free
和sleep
命令来跟踪进程,以查看是否可以隔离哪个命令导致内存使用...
再次编辑:所以“双倍”RAM 使用的罪魁祸首是 SquashFS。因此,看起来我应该使用 gzip 而不是 lzma 重新压缩文件系统。好的,部分谜团解开了。
但这仍然没有处理切换 root 后 initramfs 继续使用 RAM 的问题。所以这仍然是个谜。
我想知道内核是否会尝试在内部卸载 initramfs 但无法这样做,因为上面安装了一些东西?但这没有意义,因为在您切换 root 之前,您总是会从 initramfs 挂载一些东西......
我假设您指的是“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”。