基于Linux的固件,如何实现好的更新方式?
我正在使用alix 2d13开发一个基于linux的设备 我开发了一个脚本,负责创建映像文件、创建分区、安装引导加载程序(syslinux)、内核和initrd,并负责将根文件系统文件放入正确的分区 配置文件位于tmpfs文件系统上,在系统启动时由读取驻留在自己分区上的XML文件的软件创建 我正在寻找更新文件系统的方法,我考虑了两种解决方案:基于Linux的固件,如何实现好的更新方式?,linux,firmware,buildroot,Linux,Firmware,Buildroot,我正在使用alix 2d13开发一个基于linux的设备 我开发了一个脚本,负责创建映像文件、创建分区、安装引导加载程序(syslinux)、内核和initrd,并负责将根文件系统文件放入正确的分区 配置文件位于tmpfs文件系统上,在系统启动时由读取驻留在自己分区上的XML文件的软件创建 我正在寻找更新文件系统的方法,我考虑了两种解决方案: 固件更新是一个压缩文件,可能包含内核、initrd和/或rootfs分区,这样,在重新启动时,initrd将负责将rootfs映像添加到正确的分区 固件
- 固件更新是一个压缩文件,可能包含内核、initrd和/或rootfs分区,这样,在重新启动时,initrd将负责将rootfs映像添加到正确的分区李>
- 固件更新是一个压缩文件,可能包含两个tar归档文件,一个用于引导,另一个用于根文件系统
您觉得怎么样?您可以在提取tar文件之前快速格式化分区。或者使用映像解决方案,但使用尽可能最小的映像,并在dd之后调整文件系统大小(尽管这对于只读存储不是必需的)您可以使用单独的分区进行更新(例如Side1/Side2)。 现有内核rootfs位于Side1中,然后将更新放在Side2中并切换。
这样可以减少磨损并延长使用寿命,但设备的成本会更高。我采用了以下方法。它在某种程度上是基于“构建与Murphy兼容的嵌入式Linux系统”一文的。我使用了那篇文章中描述的versions.conf内容,而不是cfgsh内容
- 使用一个引导内核,其任务是循环装载“主”根文件系统。如果您需要一个较新的内核,那么在您循环回挂载它之后,就可以将kexec转换到该较新的内核中。我选择将引导内核的完整init与busybox和kexec(都是静态链接的)一起放在initramfs中,我编写的init是一个简单的shell脚本
- 一个或多个“主操作系统”根文件系统作为磁盘映像文件存在于“操作系统映像”文件系统上。引导内核根据versions.conf文件选择其中一个。我只维护两个主要的OS映像文件,即当前文件和回退文件。如果当前的一个失败了(稍后将详细介绍故障检测),那么引导内核将引导回退。如果两者都失败或没有回退,引导内核将提供一个shell
- 系统配置位于单独的分区上。这通常不会升级,但没有理由不升级
- 总共有四个分区:引导、操作系统映像、配置和数据。数据分区用于用户应用程序,用于频繁编写。引导永远不会以读/写方式安装。在升级过程中,操作系统映像仅以读/写方式(重新)装载。只有当配置内容需要更改时(希望永远不会更改),才以读/写方式装载配置。数据总是以读/写方式装入
- 每个磁盘映像文件都包含一个完整的Linux系统,包括内核、初始化脚本、用户程序(例如busybox、产品应用程序)和在第一次引导时复制到配置分区的默认配置。文件的大小可以满足其中的所有内容。只要我有足够的增长空间,以便OS映像分区始终足够大,可以容纳三个主OS映像文件(在升级期间,在提取新映像之前,我不会删除旧的备份),我就可以允许主OS映像根据需要增长。这些图像文件始终(回送)以只读方式装入。使用这些文件还可以解决在rootfs中升级单个文件失败的问题
- 升级是通过将自解压沥青球转移到tmpfs来完成的。此脚本的开头将重新装载OS映像读/写,然后将新的主OS映像提取到OS映像文件系统,然后更新versions.conf文件(使用“murphy”文章中描述的重命名方法)。完成此操作后,我触摸一个指示已进行升级的戳记文件,然后重新启动
- 引导内核将查找此戳记文件。如果找到它,它会将其移动到另一个戳记文件,然后引导新的主OS映像文件。当主操作系统映像文件成功启动时,它将删除戳记文件。如果没有,看门狗将触发重新启动,然后引导内核将看到这一点并检测到故障
- 您将注意到在升级过程中有几个可能的故障点:在升级过程中同步versions.conf,触摸/删除戳记文件(三个实例)。我无法找到一种方法来进一步减少这些,实现我想要的一切。如果有人有更好的建议,我很乐意听。写入操作系统映像时也可能发生文件系统错误或电源故障,但我希望ext3文件系统在这种情况下能够提供一些生存的机会