分类:
2009-11-28 16:39:05
最近参与开发的一个嵌入式设备对系统的稳定性、可靠性和可恢复性提出了较高的要求。特别地,有这些问题要考虑:当系统在更新关键文件(如内核)时突然断电,能否让系统重启后恢复到断电前瞬间的状态?如果不能恢复到断电前瞬间的状态,那能否恢复到最近的一次正确配置,让系统不致于死机?
可靠性和可恢复性难以保证的一个原因是,在一般的操作系统用户空间写文件到存储设备,要经历如下的一个过程:用户空间文件缓冲(如果用了标准IO)-->内核文件缓冲-->内核输出到存储设备的输出缓冲-->存储设备,只要全过程中的任一环节出了问题,可靠性等就难以保证。上述各环节彼此之间是非阻塞的,前一环节不必等后一环节完成就可成功返回。例如fwrite并fflush了文件内容到了内核文件缓冲,并不能保证这些内容已进入了内核的输出缓冲,按照APUE上的说法,为了提高读写效率,内核文件缓冲到内核输出缓冲一般要延迟(一般是30s),这是一个延迟写的过程。
严格的可靠性保证。这只能通过硬件保证,例如提供一个UPS电源(不间断电源),系统突然断电时,UPS提供续电并给操作系统一个中断,让操作系统启动一个清理服务例程来保证可靠性。
准可靠性保证。一般的商用嵌入式系统因成本等原因是不可能备有UPS电源的,这就只能通过软件来近似保证了,原则上只要减少文件的更新所用的时间,根据随机性原理,更新过程中突然断电的概率就会变小。对于小文件,更新速度的最大瓶颈一般在内核文件缓冲到内核输出缓冲这一步,所以一般都在fflush文件后,就调用fsync来加速文件输出到内核输出缓冲,当然这些是以牺牲效率为代价的。
硬件复位。提供一个硬件按钮,供复位到出厂配置或最近的一次配置,如很多电子词典就有一个复位孔。硬件复位的优点是任何时候都能“一键还原”,缺点是实现比较难。考虑一个嵌入式linux的启动过程,有如下几步:bootloader(相当于PC上的BIOS+GRUB)-->内核-->应用程序。一个完整的硬件复位应能做到对这三步的硬复位,即必须校验上述三者的正确性,然后作出相应的响应,例如在bootloader层或内核层出了问题,我们执行文件恢复操作就得在NONOS下进行的,即实现裸文件操作(raw ops)。所幸的是,很多时候,我们一般只会更新应用程序,这个时候在强大的操作系统下,我们可以轻松地为所欲为。
软件复位。软硬件复位的区别是复位触发点不同,软件复位的触发点是软件自检,而硬复位的触发点一般是硬件中断。对于无人看管的设备,硬件中断无从触发,这时候就必须有软件自检复位了。还是以前面提到的嵌入式linux启动过程为例,只要这三者在自己启动时都进行自检,如果自检出错,就回滚到冗余备份的老版本(对存储有点小挑战),则可恢复性就几乎perfect了。至于如何自检,最简单的就是文件完整性和安全性保证了,这些在信息安全里面讲的多了。实际中,一般只检查完整性,可以对每个文件生成一个校验文件(如md5或pgp),自检时发现新文件校验不正确,使用备份的老文件就可以了。当然了,这里有个鸡和蛋的问题了,自检的启动也是代码过程,如果自检代码都破坏了...振作一点,要做到自检代码不破坏,让它只读就行了,例如在应用程序层,你完全可以写一个永远正确并永不更新的只读程序,这个程序用来启动其它可能会被更新的应用程序。
最后,本文只是个人的一点看法,欢迎大家提出其它好的建议。