利用yaffs_GetTnode怎么映射文件地址

介绍

今天就跟大家聊聊有关利用yaffs_GetTnode怎么映射文件地址,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

yaffs文件系统在更新文件数据的时候,会分配一块新的块,也就是说,同样的文件偏移地址,在该地址上的数据更新前和更新后,其对应的闪存上的存储地址是不一样的。那么,如何根据文件内偏移地址确定flash存储地址呢?最容易想到的办法,就是在内存中维护一张映射表。由于flash基本存储单位是块,因此,只要将以块描述的文件偏移量作为表索引,将闪存块序号作为表内容,就可以解决该问题了。但是这个方法有几个问题,首先就是在做寻求操作的时候,要从表项0开始按序搜索,对于大文件会消耗很多时间,其次是在建立映射表的时候,无法预计文件大小的变化,于是就可能在后来的操作中频繁释放分配内存以改变表长,造成内存碎片.yaffs的解决方法是将这张大的映射表拆分成若干个等长的小表,并将这些小表组织成树的结构,方便管理。我们先看小表的定义:

struct yaffs_tnode {

struct yaffs_tnode *内部(YAFFS_NTNODES_INTERNAL);

};

YAFFS_NTNODES_INTERNAL定义为(YAFFS_NTNODES_LEVEL0/2),而YAFFS_NTNODES_LEVEL0定义为16,所以这实际上是一个长度为8的指针数组。不管是叶子节点还是非叶节点,都是这个结构。当节点为非叶节点时,数组中的每个元素都指向下一层子节点;当节点为叶子节点时,该数组拆分为16个16位长的短整数(也有例外,后面会说到),该短整数就是文件内容在闪存上的存储位置序(即块号)。至于如何通过文件内偏移找到对应的flash存储位置,源代码所附文档(开发/yaffs/文档/yaffs-notes2。html)已经有说明,俺就不在此处饶舌了。下面看具体函数。

为了行文方便,后文中将yaffs_Tnode这个指针数组称为“一组”Tnode,而将数组中的每个元素称为“一个”Tnode。树中的每个节点,都是“一组”Tnode。

先看映射树的节点的分配。

struct yaffs_Tnode * yaffs_get_tnode (struct yaffs_dev * dev)

{

struct yaffs_Tnode * tn=yaffs_alloc_raw_tnode (dev);

如果(tn) {

memset (tn 0开发→tnode_size);

dev→n_tnodes + +;

}

dev→checkpoint_blocks_required=0;/*力重算*/

返回tn;

}

调用yaffs_GetTnodeRaw分配节点,然后将得到的节点初始化为零。

静态yaffs_Tnode * yaffs_GetTnodeRaw (yaffs_Device * dev)

, {

yaffs_Tnode * tn=零;

/*如果没有离开更*/

如果(! dev→freeTnodes) {

yaffs_CreateTnodes (dev YAFFS_ALLOCATION_NTNODES);

,}

当前所有空闲节点组成一个链表,dev→freeTnodes是这个链表的表头。我们假定已经没有空闲节点可用,需通过yaffs_CreateTnodes创建一批新的节点。

静态int yaffs_CreateTnodes (yaffs_Device * dev, int nTnodes)

, {

,……

tnodeSize=(dev→tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;

newTnodes=YMALLOC (nTnodes * tnodeSize);

mem=(__u8 *) newTnodes;

}

(其实在最新版本的yaffs中已经加入了板缓冲区,这样提高了效率)上面说过,叶节点中一个Tnode的位宽默认为16位,也就是可以表示65536个块。对于时下的大容量flash,块的大小为2 k,因此在默认情况下yaffs2所能寻址的最大闪空间就是128。为了能将yaffs2用于大容量上,代码作者试图通过两种手段解决这个问题。第一种手段就是这里的dev→tnodeWidth,通过增加单个Tnode的位宽,就可以增加其所能表示的最大块Id;另一种手段是我们后面将看到的块组,通过将若干个块合成一组用同一个Id来表示,也可以增加系统所能寻址的块范围。

俺为了简单,分析的时候不考虑这两种情况,因此tnodeWidth取默认值16日也不考虑将多个块合成一组的情况,只在遇到跟这两种情况有关的代码时作简单说明。

在32位的系统中,指针的宽度为32位,而块Id的宽度为16位,因此相同大小的Tnode组,可以用来表示N个非叶Tnode(作为指针使用),也可以用来表示N * 2个叶子Tnode(作Id为块使用)。代码中分别用YAFFS_NTNODES_INTERNAL和YAFFS_NTNODES_LEVEL0来表示。前者取值为8,后者取值为16。从这里我们也可以看出若将yaffs2用于64位系统需要作哪些修改。针对上一段叙述的问题,俺以为在内存不紧张的情况下,不如将叶节点Tnode和非叶节点Tnode都设为一个指针的长度。分配得到所需的内存后,就将这些空闲空间组成Tnode链表:

(i=0;我& lt;nTnodes 1;我+ +){

咕咕叫=(yaffs_Tnode *)和mem[我* tnodeSize];

下=(yaffs_Tnode *)和mem [(i + 1) * tnodeSize];

利用yaffs_GetTnode怎么映射文件地址