-
NandFlash 读CACHE简介
由于磁盘属于低速设备,磁盘的读写速度远远低于CPU,所以为了解决这种速度不匹配的问题,SylixOS提供了对应块设备的缓冲器。与此对应的,为了提高NandFlash的读速度,SylixOS也为NandFlash提供了一种读CACHE机制。为了不影响写平衡软件对坏块的管理,该缓冲机制在NandFlash写一个扇区时,将相关的扇区CACHE全部设为读不命中;当NandFlash擦除一个块时,将块内所有的扇区CACHE设为读不命中。
-
技术实现
SylixOS中关于NandFlash读CACHE的内容主要在"libsylixos/SylixOS/fs/nandRCache"目录下,主要实现了读CACHE的创建、删除操作,以及节点的申请、释放操作。其中,读CACHE的创建函数接口如程序清单 2-1所示。
程序清单 2-1读CACHE创建函数
#include <SylixOS.h> LW_API ULONG API_NandRCacheCreate(PVOID pvNandRCacheMem, size_t stMemSize, ULONG ulPageSize, ULONG ulSpareSize, ULONG ulPagePerBlock, PLW_NRCACHE_CB *ppnrcache);
函数API_NandRCacheCreate原型分析:
- 此函数成功返回ERROR_NONE,失败返回错误码;
- 参数pvNandRCacheMem是缓存内存地址;
- 参数stMemSize是缓存内存大小;
- 参数ulPageSize是每个页面数据区大小;
- 参数ulSpareSize是每个页面扩展区大小;
- 参数ulPagePerBlock是每一块页面的个数;
- 参数ppnrcache是需要返回的创建成功的控制块。
使用API_NandRCacheCreate函数创建CACHE成功时,最后一个入参将返回NandFlash的读CACHE控制块,该控制块的详细信息如程序清单 2-2所示。
程序清单 2-2读CACHE管理控制块
typedef struct {
PLW_NRCACHE_NODE NRCACHE_pnrcachenBuffer; /* nand flash 所有的缓冲 */ ULONG NRCACHE_ulPagePerBlock; /* 每一个块的页面个数 */ ULONG NRCACHE_ulnCacheNode; /* CACHE 中包含的节点个数 */ INT NRCACHE_iHashSize; /* hash 表大小 */ PLW_LIST_LINE *NRCACHE_pplineHash; /* 搜索 hash 表 */ PLW_LIST_RING NRCACHE_pringLRU; /* 有效点中最近最少使用表 */ PLW_LIST_LINE NRCACHE_plineFree; /* 空闲表头 */ } LW_NRCACHE_CB; typedef LW_NRCACHE_CB *PLW_NRCACHE_CB; /* nand read cache 控制块 */
NandFlash的读CACHE创建过程主要包括开辟Hash表内存、开辟初始化控制块内存以及初始化每个节点内存使用情况。和块设备的DiskCACHE类似,NandFlash读CACHE以NODE节点管理CACHE缓存,每一个NODE节点都对应着一页缓存,NODE节点则以LRU(Least Recently Used)的方式组成循环链表,方便刷新脏节点。对于已经缓存的扇区,则通过HASH表与链表结合的方式进行快速索引。空闲的节点单独构成一个链表,方便节点的快速申请。
管理CACHE缓存的NODE节点详细信息如程序清单 2-3所示。
程序清单 2-3 NODE节点控制块
typedef struct { LW_LIST_LINE NRCACHEN_lineManage; /* 空闲链表 或 hash */ LW_LIST_RING NRCACHEN_ringLRU; /* LRU 链 */ ULONG NRCACHEN_ulChunkNo; /* 扇区号 */ caddr_t NRCACHEN_pcChunk; /* 数据区缓冲 */ caddr_t NRCACHEN_pcSpare; /* 扩展区缓冲 */ } LW_NRCACHE_NODE; typedef LW_NRCACHE_NODE *PLW_NRCACHE_NODE; /* 缓冲节点 */
对于NODE节点的操作主要包括申请、查找、释放等操作,其中节点申请函数接口如程序清单 2-4所示。
程序清单 2-4 CACHE节点申请函数
#include <SylixOS.h> LW_API PLW_NRCACHE_NODE API_NandRCacheNodeAlloc(PLW_NRCACHE_CB pnrcache, ULONG ulChunkNo);
函数API_NandRCacheCreate原型分析:
- 此函数成功返回NODE节点,失败返回LW_NULL;
- 参数pnrcache是CACHE控制块;
- 参数ulChunkNo是需要缓存的扇区号。
函数API_NandRCacheCreate从空闲NODE池中获取节点时,若不存在空闲节点,则将从LRU表中淘汰一个最久未使用的节点。
获得指定扇区节点的函数接口如程序清单 2-5所示。
程序清单 2-5 CACHE节点查找函数
#include <SylixOS.h> LW_API PLW_NRCACHE_NODE API_NandRCacheNodeGet(PLW_NRCACHE_CB pnrcache, ULONG ulChunkNo);
函数API_NandRCacheNodeGet原型分析:
- 此函数成功返回节点控制块,失败返回LW_NULL;
- 参数pnrcache是CACHE控制块;
- 参数ulChunkNo是需要缓存的扇区号。
当API_NandRCacheNodeGet函数在CACHE中命中时,会将此节点挂入LRU表的头部,这样最近使用的数据始终保持在链表头部。
将一个有效节点释放的函数接口如程序清单 2-6所示。
程序清单 2-6 CACHE节点释放函数
#include <SylixOS.h> LW_API VOID API_NandRCacheNodeFree(PLW_NRCACHE_CB pnrcache, ULONG ulChunkNo);
函数API_NandRCacheNodeFree原型分析:
- 此函数成功返回;
- 参数pnrcache是CACHE控制块;
- 参数ulChunkNo是需要缓存的扇区号;
NandFlash的读CACHE删除操作的函数接口如程序清单 2-7所示。
程序清单 2-7读CACHE删除函数
#include <SylixOS.h> LW_API ULONG API_NandRCacheDelete(PLW_NRCACHE_CB pnrcache);
函数API_NandRCacheDelete原型分析:
- 此函数成功ERROR_NONE,失败返回PX_ERROR;
- 参数pnrcache是CACHE控制块。
-
参考资料
无