闪存的使用

    在Linux系统中,通过文件系统访问闪存是顺理成章的做法。目前支持NANDFLAsH的常用文件系统有YAFFS/YAFFS2,JFFS2和UBIFS等。它们都是记帐式的文件系统,各有特点,也有不足。
    YAFFS/YAFFS2是专为NANDFLASH写的文件系统。在YAFFS的代码里包括管理闪存带外区(OOB)的部分,而这部分代码一般认为属于设备驱动的范畴,其他文件系统里是不含这部分代码的。YAFFS是一种稳键的记帐结构的文件系统。高效率是它追求的另一个目标。它可以用在各种操作系统中(已用于Linux,WinCE,pSOS,eCos,ThreadX及各种专用操作系统中),甚至可以在没有操作系统的环境下工作。YAFFS2支持“检查点(checkpoints)”,以避免挂载过程中耗时的扫描操作,实现快速挂载。
    相对于JFFS,JFFS2有了一些改进,可以支持硬连接(hard Links),垃圾回收更有效,平衡损耗更均匀。但它在挂载时仍需要扫描寻找最新版本的闪存块,并建立RAM中的数据结构,文件系统越大,挂载时间越长,RAM开销也越大。虽然JFFS2已经通过小结节点技术减少了挂载时间,但结果仍不理想,挂载时间是s级的。
    UBIFS是JFFS2的后继(原来称作JFFS3),第1个稳定版本于2008年10月加入到Linux 2.6.27版核心中,它有一个竞争者叫LogFS。UBIFS与JFFS2的最大不同在于它的文件索引信息是写在闪存中的,而JFFS2是暂存在RAM中的。因此,UBIFS在挂载时不需要扫描全部闪存空间,挂载耗时很短(ms级);UBIFS对RAM的消耗不会随着文件系统的尺寸变大而线性增长,适用于大容量的文件系统。
    除这这些不同之外,各种闪存文件系统也存在一些共性。由于闪存的写入次数有限,为了避免局部因频繁写入而过早失效,必须使写入操作尽量均匀分布到所有位置上,即平衡损耗(wear leveling)。这导致了更新文件时必须做异位更新,而不能像在磁盘或RAM中那样简单地原位更新,从而引起一系列复杂的问题。首先,异位更新会导致闪存块中出现越来越多的过期页面,它们与有效页面混杂在一起,形成所谓的脏块(dirty blocks)。当所有的闪存块都成为脏块后,就没有闪存块可供擦除再分配了。因此,基于闪存的文件系统都有垃圾回收器,用于将分散的过期页面集中在一起,形成空闪存块(free blocks)。由此引起的另一个问题是文件系统在使用时不能用到接近填满,否则也会导致类似的问题。其次,树状结构的文件索引中存在大量的互相引用,某个节点的改变会引起该节点本身及直接和间接引用它的一系列节点的异位更新。
    从以上的分析可以看出,NANDFLASH上的文件系统是一把双刃剑。它确实可以提供清晰的软件层次和使用上的方便,但同时也会降低操作效率,并具有潜在的可靠性问题。关键是如何合理使用,扬长避短。其实,对于写入量小(一个擦除块之内),并且不频繁的数据,可以跳过文件系统,通过ioctrl()函数直接操作闪存。这样做的缺点是破坏了软件层次,要求应用软件开发人员了解一部分硬件的细节,在应用程序中完成一些本应属于驱动程序的底层功能(如块擦除,发现和标记坏块等);优点是可以抛开复杂的文件系统,不需要挂载及卸载,更不存在文件系统的完整性问题,平衡损耗等措施可以视需要取舍,尤其在意外掉电时,该方法可将所有的读/写错误都限制在相对较小的局部,具有较好的应对掉电的能力。

你可能感兴趣的:(闪存的使用)