我正在尝试为基于 Linux 的嵌入式系统设想一种固件更新机制,而无需额外的 initrd/initramfs/其他任何东西。在具有只读安装根的正在运行的系统中,我使用 dd 复制新的根映像(驻留在辅助数据分区上)。
问题是,有一半的情况我最终会遇到根文件系统损坏的情况。我不明白为什么会发生这种情况,因为我知道该分区是只读的,并且我在重新启动之前进行了同步(我通过将“b”写入 /proc/sysrq-trigger 来重新启动)。有人请赐教。
答案1
您正在覆盖已安装的文件系统。一旦文件系统驱动程序尝试从中读取任何内容,您注定会遇到麻烦。
您需要确保在编写新固件后,其他任何东西都不能读取或写入该分区。
人们通常为规避该问题所做的事情似乎是使用引导加载程序来刷新新固件。它通常完全驻留在 RAM 中,因此不需要访问您的分区。
编辑:另一种方法是在第二个分区上安装另一个最小系统,其唯一目的是将映像文件刷新到第一个分区。当更新到期时,您只需将映像复制到正确的位置,更新引导加载程序(从第二个分区引导)并重新启动。写入映像后,重置引导加载程序并再次重新启动。
答案2
挂载后,您无法覆盖根文件系统,即使是只读的。
你什么能要做的是挂载一个包含根文件系统中所有文件的 tmpfs,然后调用pivot_root 切换到 tmpfs 并卸载旧根。
对于已经启动的系统来说,这可能是不可能的,因为卸载旧的根文件系统意味着从该系统运行的所有程序都必须退出或执行程序。
使用这种方法的最可行的方法可能是有一个 /sbin/tmpfs-init 程序来完成所有这些工作,然后执行新的 init。即使这一点也很难做到。