(萊昂氏unix原始碼分析導讀-44) 檔案系統資源
by cszhao1980
一個裝置被mount進系統後,就被稱為一個檔案系統。它有兩類資源:
(1) 磁碟inode資源;
(2) 普通盤塊資源。
1. 磁碟inode資源
對於inode資源,unix v6採用了一種很簡單的管理方法。即在超級塊中維護一個free inode
資源陣列(max 100 entry),存放可用的inode資源(inode id):
5568: int s_ninode; /* number of in core I nodes (0-100) */
5569: int s_inode[100]; /* in core free I nodes */
5571: char s_ilock; /* lock during I list manipulation */
當程序請求inode資源時,先檢查free inode陣列,看是否還有空閒項:
(1) 有:直接分配給程序。
(2) inode項已經耗盡:
先執行一個free inode陣列重建過程——Loop所有的inode盤塊,找到空閒的inode項,
存入free inode陣列;然後再從空閒陣列中分配。
基本上,上面描述的就是inode資源分配函式“ialloc”的分配演算法,唯一需要多注意的
是free inode資源陣列重建過程中,對空閒磁碟inode的判斷方法:
(1) 7101行: i_mode為0;
(2) 7104 ~ 7106行:還需要Loop系統inode表,看該inode是否正在使用。
相應的,unix v6還提供了inode資源釋放函式ifree(dev, ino)——這個函式的實現非常簡單:
(1) 當free inode陣列“不滿”時,將要釋放的inode資源放入該陣列;否則,直接return;
(2) 而且,遇到檔案系統“上鎖”時,也直接return
——這也難怪,按照前面的描述,ialloc()本身就是“自適應”的函式,根本不需要ifree()配合。
ifree的存在只是錦上添花而已。
【效能考慮】:
上述演算法中的free inode陣列的全域性過程會不會成為效能瓶頸?
應該不會:
(1)一個盤塊可容納256/16 = 16個磁碟inode項。而一個檔案僅需要一個磁碟inode項(1/16塊)——對
大多數檔案來說,這遠遠小於檔案內容所佔用的磁碟塊數。因此,通常情況下一個檔案系統中
只需分配很小部分的盤塊作inode資源。
而我們的模型所配置的RK磁碟,總共才有4800塊盤塊,因此,這個重建過程不會太慢;
(2)一次重建可以恢復100個空閒資源——在當時的環境下,重建的次數也不會太頻繁。
2. 盤塊資源
超級塊中用於盤塊資源管理的變數與inode管理的極其相似:
5565: int s_nfree; /* number of in core free blocks (0-100) */
5567: int s_free[100]; /* in core free blocks */
5570: char s_flock; /* lock during free list manipulation */
但是,事實上,對於盤塊資源的管理,unix v6採用了完全不同的方式。
所有的空閒盤塊被按照100個一組分為若干組,而每組的第一個盤塊指向下一組——它記錄的內容:
(1) 第一個word是下一組空閒盤塊的個數;
(2) 2~…是下一組空閒盤塊的塊號。
因此,這些空閒盤塊組就形成了一個鏈狀結構,如下所示:
超級塊中的free block資源陣列記錄的就是第1組盤塊資訊。
當分配資源時,從s_free數組裡逆序進行分配,當僅剩一個entry時,就讀取該盤塊,獲取下一組空閒盤塊。
當釋放資源時,如果s_free陣列不滿,則直接返回到該陣列內;
否則,利用新釋放的盤塊新建一個空閒組,將s_free陣列所記錄的盤塊號寫入盤塊中——即使
用“頭插法”插入新組。
理解了上述過程,則資源分配和回收函式alloc()和free()就顯得比較簡單了。
最後我們看一下itrunc函式,它用來進行回收指定檔案所佔用的盤塊資源,它只有一個引數,即該文
件的inode。呼叫該函式後,檔案佔用的盤塊資源被回收:
(1) 檔案inode的i_addr陣列以及i_size0和i_size1都被置0;
(2) 如果原檔案為大檔案,大檔案標誌也被清除。