溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

利用yaffs_GetTnode怎么映射文件地址

發(fā)布時間:2021-07-21 09:20:08 來源:億速云 閱讀:155 作者:Leah 欄目:互聯(lián)網(wǎng)科技

今天就跟大家聊聊有關(guān)利用yaffs_GetTnode怎么映射文件地址,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

yaffs文件系統(tǒng)在更新文件數(shù)據(jù)的時候,會分配一塊新的chunk,也就是說,同樣的文件偏移地址,在該地址上的數(shù)據(jù)更新前和更新后,其對應(yīng)的flash上的存儲地址是不一樣的。那么,如何根據(jù)文件內(nèi)偏移地址確定flash存儲地址呢?最容易想到的辦法,就是在內(nèi)存中維護一張映射表。由于 flash基本存儲單位是chunk,因此,只要將以chunk描述的文件偏移量作為表索引,將flash chunk序號作為表內(nèi)容,就可以解決該問題了。但是這個方法有幾個問題,首先就是在做seek操作的時候,要從表項0開始按序搜索,對于大文件會消耗很多時間;其次是在建立映射表的時候,無法預(yù)計文件大小的變化,于是就可能在后來的操作中頻繁釋放分配內(nèi)存以改變表長,造成內(nèi)存碎片。yaffs的解決方法是將這張大的映射表拆分成若干個等長的小表,并將這些小表組織成樹的結(jié)構(gòu),方便管理。我們先看小表的定義:

struct yaffs_tnode {

struct yaffs_tnode *internal[YAFFS_NTNODES_INTERNAL];

};

YAFFS_NTNODES_INTERNAL定義為(YAFFS_NTNODES_LEVEL0 / 2),而YAFFS_NTNODES_LEVEL0定義為16,所以這實際上是一個長度為8的指針數(shù)組。不管是葉子節(jié)點還是非葉節(jié)點,都是這個結(jié)構(gòu)。當(dāng)節(jié)點為非葉節(jié)點時,數(shù)組中的每個元素都指向下一層子節(jié)點;當(dāng)節(jié)點為葉子節(jié)點時,該數(shù)組拆分為16個16位長的短整數(shù)(也有例外,后面會說到),該短整數(shù)就是文件內(nèi)容 在flash上的存儲位置(即chunk序號)。至于如何通過文件內(nèi)偏移找到對應(yīng)的flash存儲位置,源代碼所附文檔(Development/yaffs/Documentation/yaffs-notes2.html)已經(jīng)有說明,俺就不在此處饒舌了。下面看具體函數(shù)。

為了行文方便,后文中將yaffs_Tnode這個指針數(shù)組稱為“一組”Tnode,而將數(shù)組中的每個元素稱為“一個”Tnode。樹中的每個節(jié)點,都是“一組”Tnode。

先看映射樹的節(jié)點的分配。

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;

}

調(diào)用yaffs_GetTnodeRaw分配節(jié)點,然后將得到的節(jié)點初始化為零。

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);

 }

當(dāng)前所有空閑節(jié)點組成一個鏈表,dev->freeTnodes是這個鏈表的表頭。我們假定已經(jīng)沒有空閑節(jié)點可用,需通過yaffs_CreateTnodes創(chuàng)建一批新的節(jié)點。

static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes)

 {

 ......

tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;

newTnodes = YMALLOC(nTnodes * tnodeSize);

mem = (__u8 *)newTnodes;

}

(其實在最新版本的yaffs中已經(jīng)加入了slab緩沖區(qū),這樣提高了效率)上面說過,葉節(jié)點中一個Tnode的位寬默認為16位,也就是可以表示65536個chunk。對于時下的大容量flash,chunk的大小為2K,因 此在默認情況下yaffs2所能尋址的最大flash空間就是128M。為了能將yaffs2用于大容量flash上,代碼作者試圖通過兩種手段解決這個問題。第一種手段就是這里的dev->tnodeWidth,通過增加單個Tnode的位寬,就可以增加其所能表示的最大chunk Id;另一種手段是我們后面將看到的chunk group,通過將若干個chunk合成一組用同一個id來表示,也可以增加系統(tǒng)所能尋址的chunk范圍。

俺為了簡單,分析的時候不考慮這兩種情況,因此tnodeWidth取默認值16,也不考慮將多個chunk合成一組的情況,只在遇到跟這兩種情況有關(guān)的代碼時作簡單說明。

在32位的系統(tǒng)中,指針的寬度為32位,而chunk id的寬度為16位,因此相同大小的Tnode組,可以用來表示N個非葉Tnode(作為指針使用),也可以用來表示N * 2個葉子Tnode(作為chunk id使用)。代碼中分別用YAFFS_NTNODES_INTERNAL和YAFFS_NTNODES_LEVEL0來表示。前者取值為8,后者取值為16。從這里我們也可以看出若將yaffs2用于64位系統(tǒng)需要作哪些修改。 針對上一段敘述的問題,俺以為在內(nèi)存不緊張的情況下,不如將葉節(jié)點Tnode和非葉節(jié)點Tnode都設(shè)為一個指針的長度。分配得到所需的內(nèi)存后,就將這些空閑空間組成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。完成鏈表構(gòu)造后,還要遞增統(tǒng)計量,并將新得到的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;

 }

回到y(tǒng)affs_GetTnodeRaw,創(chuàng)建了若干組新的Tnode以后,從中切下所需的Tnode,并修改空閑鏈表表頭指針:

if (dev->freeTnodes) {

tn = dev->freeTnodes;

dev->freeTnodes = dev->freeTnodes->internal[0];

dev->nFreeTnodes--;

 }

看完上述內(nèi)容,你們對利用yaffs_GetTnode怎么映射文件地址有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI