您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關利用yaffs_GetTnode怎么映射文件地址,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
yaffs文件系統在更新文件數據的時候,會分配一塊新的chunk,也就是說,同樣的文件偏移地址,在該地址上的數據更新前和更新后,其對應的flash上的存儲地址是不一樣的。那么,如何根據文件內偏移地址確定flash存儲地址呢?最容易想到的辦法,就是在內存中維護一張映射表。由于 flash基本存儲單位是chunk,因此,只要將以chunk描述的文件偏移量作為表索引,將flash chunk序號作為表內容,就可以解決該問題了。但是這個方法有幾個問題,首先就是在做seek操作的時候,要從表項0開始按序搜索,對于大文件會消耗很多時間;其次是在建立映射表的時候,無法預計文件大小的變化,于是就可能在后來的操作中頻繁釋放分配內存以改變表長,造成內存碎片。yaffs的解決方法是將這張大的映射表拆分成若干個等長的小表,并將這些小表組織成樹的結構,方便管理。我們先看小表的定義:
struct yaffs_tnode {
struct yaffs_tnode *internal[YAFFS_NTNODES_INTERNAL];
};
YAFFS_NTNODES_INTERNAL定義為(YAFFS_NTNODES_LEVEL0 / 2),而YAFFS_NTNODES_LEVEL0定義為16,所以這實際上是一個長度為8的指針數組。不管是葉子節點還是非葉節點,都是這個結構。當節點為非葉節點時,數組中的每個元素都指向下一層子節點;當節點為葉子節點時,該數組拆分為16個16位長的短整數(也有例外,后面會說到),該短整數就是文件內容 在flash上的存儲位置(即chunk序號)。至于如何通過文件內偏移找到對應的flash存儲位置,源代碼所附文檔(Development/yaffs/Documentation/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);
if (tn) {
memset(tn, 0, dev->tnode_size);
dev->n_tnodes++;
}
dev->checkpoint_blocks_required = 0;/* force recalculation */
return tn;
}
調用yaffs_GetTnodeRaw分配節點,然后將得到的節點初始化為零。
static yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device * dev)
{
yaffs_Tnode *tn = NULL;
/* If there are none left make more */
if (!dev->freeTnodes) {
yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES);
}
當前所有空閑節點組成一個鏈表,dev->freeTnodes是這個鏈表的表頭。我們假定已經沒有空閑節點可用,需通過yaffs_CreateTnodes創建一批新的節點。
static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes)
{
......
tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
newTnodes = YMALLOC(nTnodes * tnodeSize);
mem = (__u8 *)newTnodes;
}
(其實在最新版本的yaffs中已經加入了slab緩沖區,這樣提高了效率)上面說過,葉節點中一個Tnode的位寬默認為16位,也就是可以表示65536個chunk。對于時下的大容量flash,chunk的大小為2K,因 此在默認情況下yaffs2所能尋址的最大flash空間就是128M。為了能將yaffs2用于大容量flash上,代碼作者試圖通過兩種手段解決這個問題。第一種手段就是這里的dev->tnodeWidth,通過增加單個Tnode的位寬,就可以增加其所能表示的最大chunk Id;另一種手段是我們后面將看到的chunk group,通過將若干個chunk合成一組用同一個id來表示,也可以增加系統所能尋址的chunk范圍。
俺為了簡單,分析的時候不考慮這兩種情況,因此tnodeWidth取默認值16,也不考慮將多個chunk合成一組的情況,只在遇到跟這兩種情況有關的代碼時作簡單說明。
在32位的系統中,指針的寬度為32位,而chunk id的寬度為16位,因此相同大小的Tnode組,可以用來表示N個非葉Tnode(作為指針使用),也可以用來表示N * 2個葉子Tnode(作為chunk id使用)。代碼中分別用YAFFS_NTNODES_INTERNAL和YAFFS_NTNODES_LEVEL0來表示。前者取值為8,后者取值為16。從這里我們也可以看出若將yaffs2用于64位系統需要作哪些修改。 針對上一段敘述的問題,俺以為在內存不緊張的情況下,不如將葉節點Tnode和非葉節點Tnode都設為一個指針的長度。分配得到所需的內存后,就將這些空閑空間組成Tnode鏈表:
for(i = 0; i < nTnodes -1; i++) {
curr = (yaffs_Tnode *) &mem[i * tnodeSize];
next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];
curr->internal[0] = next;
}
每組Tnode的第一個元素作為指針指向下一組Tnode。完成鏈表構造后,還要遞增統計量,并將新得到的Tnodes掛入一個全局管理鏈表yaffs_TnodeList:
dev->nFreeTnodes += nTnodes;
dev->nTnodesCreated += nTnodes;
tnl = YMALLOC(sizeof(yaffs_TnodeList));
if (!tnl) {
T(YAFFS_TRACE_ERROR, (TSTR ("yaffs: Could not add tnodes to management list" TENDSTR)));
} else {
tnl->tnodes = newTnodes;
tnl->next = dev->allocatedTnodeList;
dev->allocatedTnodeList = tnl;
}
回到yaffs_GetTnodeRaw,創建了若干組新的Tnode以后,從中切下所需的Tnode,并修改空閑鏈表表頭指針:
if (dev->freeTnodes) {
tn = dev->freeTnodes;
dev->freeTnodes = dev->freeTnodes->internal[0];
dev->nFreeTnodes--;
}
看完上述內容,你們對利用yaffs_GetTnode怎么映射文件地址有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。