我正在开发一个嵌入式 Linux,使用 u-boot 作为引导加载程序和 systemd init 系统。这些工具仅限于标准 busybox。
在分析一些问题时,我发现根文件系统是只读的,这导致了问题。原因是某些服务和程序依赖于可写的根文件系统,导致故障。
经过一段时间的研究,我发现根文件系统只有在断电时才是只读的。 (当遇到某些错误时,主单元会触发电源回收。)我怀疑当根文件系统尝试写入某些关键文件或更新某些服务/进程时,在电源故障时会在文件系统上设置错误标志。下次启动时,fsck 会读取该标志并将根挂载/重新挂载为只读,或者 fsck 强制进入某种恢复模式(我不知道是否存在任何恢复模式)。
我的假设正确吗?如果是这样,那么错误时在 FS 上设置的 fs 标志是什么?如何防止 root 作为 RO 启动?
笔记:
根文件系统使用“errors=continue”挂载。因此,如果 fsck 读取重新安装选项的超级块,它应该忽略该错误并重新安装为 RW。
我尝试重现该情况,在运行 dd 命令时关闭电源,但从未能够重现。
附加问题:哪个 udev/systemd 魔法挂载 root fs?
答案1
启动时,您应该检查文件系统以查看系统是否正确关闭或是否崩溃,并在后一种情况下执行必要的恢复操作。在现代日志文件系统上,这通常意味着可以自动完成的简单快速的日志恢复操作。
根文件系统检查和安装通常由 initramfs/initrd 完成,但在嵌入式系统上您可能有也可能没有它。
如果您不使用 initramfs,那么传统的方法是让内核总是最初将根文件系统挂载为只读(使用启动选项root=/dev/<whatever> ro
,然后启动脚本将首先fsck
在其上运行(假设对于所使用的文件系统类型是必需的),然后在执行任何操作之前将根文件系统重新挂载为读/写模式别的。
如果 initramfs 没有检查根文件系统(可能是因为它没有被使用),那么用于在根文件系统上运行文件系统检查的标准 systemd 服务名称将被命名为systemd-fsck-root.service
。检查后,我找不到负责使用 systemd 重新挂载根文件系统的服务的名称。
如果启动时根文件系统检查需要修改根文件系统,它通常会在之后触发另一次重新启动,因为修改可能会影响内核已经读取并正在缓存的内容,并且在对根文件系统进行更正后现在会不一致。磁盘由fsck
.