我的嵌入式 Linux 上出现了一个(我认为)非常特殊的情况,我无法正确解决......
由于在启动时挂载文件系统之前要执行特定(自定义)检查,我使用初始 ramdisk 来检查和挂载所有请求的文件系统,然后在 init 完成时将它们传输到根文件系统(因此不/etc/fstab
使用挂载设备,而是通过驻留在初始 ramdisk 内的脚本挂载它们)。
更具体地说,首先挂载/boot
分区(mmcblk1p1
)(以只读模式);在该分区内,我有一个文件(rootfs.squashfs
),对应于目标根文件系统的 squashfs 映像......因此,经过一些其他操作(与本文的目的无关)后,初始 ramdisk 脚本最终挂载了 squashfs 映像/rootfs
,并在 init 脚本的末尾切换到系统根目录/rootfs
(通过switch-root
命令);
问题出现在系统重启(或关机或断电)时:当系统尝试卸载所有已挂载的文件系统时,卸载/boot
失败(因为设备正忙,这很明显,因为根文件系统是从位于 /boot 中的 squashfs 文件挂载的)。
有没有办法避免/boot
在重启/关机/断电时卸载,从而避免卸载失败?由于它是以只读方式安装的,所以应该没有任何风险,不是吗?还是我遗漏了什么?
附言:我不知道它是否有帮助和/或相关:我的操作系统初始化是通过 进行管理的systemd
。
实际上您不需要更改顺序。由于文件系统是只读的,因此只需告诉内核它可以稍后完成卸载(当没有剩余引用时),而不是要求它立即成功,这样就比较安全。
在
boot.mount
单位配置中,设置标志LazyUnmount=true
。https://www.freedesktop.org/software/systemd/man/latest/systemd.mount.html#LazyUnmount=
.mount
(如果您从未手动创建单元文件,它们是由扫描 fstab 的 systemd 生成器创建的;即使您不是自己创建它们,您仍然可以用插入文件覆盖挂载单元)。Systemd 支持“exitrd”功能(也称为“关闭 initramfs”),在延迟关闭期间它将转回RAM文件系统并执行您提供的脚本,然后可以以任何它想要的方式卸载“真实”根文件系统。
当找到可执行文件时,将使用 exitrd
/run/initramfs/shutdown
。在 systemd 停止所有单元并执行其最终关闭处理程序后,它不会打印“无法完成文件系统”,而是将 switch_root 设置为/run/initramfs
,将实际根文件系统放置在/oldroot
,然后执行/shutdown
脚本。