ext2讀取並產生間接塊和資料塊

2021-10-05 06:57:51 字數 2871 閱讀 5640

讀取並產生資料塊和間接塊

在學習頁快取的時候,我們看到這樣一張圖:

ext2_get_branch跟蹤這個路徑,最終到達乙個資料塊。函式中呼叫sb_bread()相繼讀取各個間接塊。每個塊的資料和從路徑得知的偏移量,可用於找到指向下乙個間接塊的指標。一直重複,直到到達乙個資料塊,這時函式返回null,表示找到資料塊了。接下來就檢查是否有別的執行緒在我們讀取的時候已經對這個檔案進行了截斷操作,然後將找到的資料塊的資訊由bh_result返回給上層函式進行資料塊的讀取。

需要向塊裝置寫入資料的情況相對就複雜一點了。這時需要建立新塊。建立新塊需要兩個資訊:

找到乙個空閒塊,作為新塊。為了使同乙個檔案的資料塊更為緊湊,核心會進行預留塊操作,這個我們稍後討論。

新塊的位址指標存放在**?直接資料塊?間接塊?幾次間接?

之前說過,ext2_get_branch函式返回null表示找到資料塊,那麼非空的情況返回的是什麼呢?是乙個indirect型別的資料,表示最後乙個間接塊的位址,以此作為檔案擴充套件的起點。我們先看indirect的定義。

typedef struct indirect;

這是乙個結構體,key表示塊號,key的值是p所指向的記憶體中的位址存放的數值。緩衝頭bh用於在記憶體中儲存塊的資料。

注意是先有p再有key,即key是用p所指向的位址中的資料來賦值的。

static inline voidadd_chain(indirect *p, struct buffer_head *bh, __le32 *v)

p->key= *(p->p = v);

p->bh= bh;

indirect例項有完整和不完整兩種狀態。完整狀態是指key不為0,而p指向key在記憶體中的位址,這時相當於塊號資訊儲存了兩次,即*p=key。不完整狀態是指key值為0的時候,這時候p所指的地方存的key還是初始值0。核心需要找到乙個空閒的塊號填充key。

什麼時候indirect例項是不完整的呢?當ext2_get_branch循著路徑試圖到達乙個資料塊時,將過程中讀取到的間接塊資訊儲存在indirect型別的陣列chain中,每一次填充chain陣列中的indirect例項,都會檢查key是否為0。如果是,則表示要尋找的資料塊不存在,即檢測到沒有指向下乙個層次間接塊(或資料塊,如果是直接分配)的指標,這時返回當前的這個不完整的indirect例項。這時候p成員指向下一層次間接塊或資料塊應該出現在間接塊中的位置,但key為0,因為該塊尚未分配。下圖就表示了這樣一種情況:需要定址間接塊所指的第三個資料塊,該塊現在尚不存在,但需要使用。這時候的p=0x1002=0x1000+2,而key=0。

我們到達不了乙個資料塊,那就要分配塊了。首先檢查當前檔案節點是否為分配工作做好準備了,即保證ext2_inode_info->i_block_alloc_info不為null,因為其中包含了分配塊時需要的資訊。接下來的工作就是搜尋空閒的資料塊了,由函式ext2_find_goal()完成。由於檔案組織的緊湊性,目標塊的位置由好到壞:

與邏輯相鄰的資料塊物理相鄰的空閒塊

與當前間接塊相鄰或相近的空閒塊

同乙個柱面的空閒塊

找到目標塊後,函式計算用於儲存間接資訊的間接塊和資料塊的數量,分別儲存在indirect_blks和count中。他們都是需要分配的塊。實際的分配工作由ext2_alloc_branch完成。

塊分配ext2_alloc_branch函式呼叫ext2_alloc_blocks對給定的新路徑分配所需的塊,並建立連線塊的間接鏈,即建立間接塊的indirect例項。所以ext2_alloc_blocks一次性把需要分配的塊都分配到了。我們看他怎麼做到的。實際上分配塊的繁重的任務是由ext2_new_blocks完成的,ext2_alloc_blocks一直重複的呼叫它直到完成目的。到現在,我們發現很多建立的工作都是再ext2_new_blocks中完成的,它通過處理預留視窗或者是檢視位圖查詢空閒塊,機制很繁瑣。先來看看ext2_new_blocks的函式原型:

ext2_fsblk_text2_new_blocks(struct inode *inode, ext2_fsblk_t goal,

unsigned long *count, int*errp);

inode表示當前檔案節點,goal是目標塊號(指定優先從哪個塊開始分配),count指定所需塊數,errp傳遞錯誤碼,函式返回已分配的塊序列中的第乙個塊號。還有一點值得注意:該函式總是分配連續的塊。函式流程如下:

其中ext2_try_to_allocate_with_rsv實現了實際分配資料塊的操作,有可能使用預留機制。函式原型如下:static ext2_grpblk_t

ext2_try_to_allocate_with_rsv(structsuper_block *sb, unsigned int group,

structbuffer_head *bitmap_bh, ext2_grpblk_t grp_goal,

struct ext2_reserve_window_node *my_rsv,//為null則不使用預留機制

unsignedlong *count)

呼~~~不想接著挖了,看了**不難,主要就是根據預留視窗和目標塊確定乙個搜尋區域,在塊分配點陣圖中搜尋連續的空閒位元位。最後講講搜尋區域的不同情況吧~

Ext2的超級塊物件

當安裝 ext2 檔案系統時 執行諸如 mount t ext2 dev sda2 mnt test 的命令 存放在 ext2 分割槽的磁碟資料結構中的大部分資訊將被拷貝到 ram中,從而使核心避免了後來的很多讀操作。那麼一些資料結構如何經常更新呢?因為所有的 ext2 磁碟資料結構都存放在 ext...

深入理解Linux核心 Ext2和Ext3檔案系統

ext2的一般特徵 1 建立ext2檔案系統時,系統管理員可以根據預期的檔案平均長度來選擇最佳塊大小 從1024b 4096b 來減少檔案碎片 2 建立ext2檔案系統時,系統管理員可以根據在給定大小的分割槽上預計存放的檔案樹來選擇給該區分配多少個索引節點。更加有效的利用磁碟空間 3 檔案系統將磁碟...

深入理解Linux核心 Ext2和Ext3檔案系統

ext2的一般特徵 1 建立ext2檔案系統時,系統管理員可以根據預期的檔案平均長度來選擇最佳塊大小 從1024b 4096b 來減少檔案碎片 2 建立ext2檔案系統時,系統管理員可以根據在給定大小的分割槽上預計存放的檔案樹來選擇給該區分配多少個索引節點。更加有效的利用磁碟空間 3 檔案系統將磁碟...