1. 程式人生 > >(萊昂氏unix原始碼分析導讀-39)inode“資源”的獲取和釋放

(萊昂氏unix原始碼分析導讀-39)inode“資源”的獲取和釋放

                                              by cszhao1980

iget()函式用於獲取inode資源,它有2個引數,裝置號和inode id。前面說過,通過這兩個引數

會唯一確定一個inode。簡單的說,該函式的作用就是將指定的磁碟inode讀入記憶體inode陣列,

Lock該項(即會設定 ILOCK flag),它返回一個指向該inode陣列項的指標。

事實上,iget()做的更多一些,它首先檢查記憶體inode陣列中,如果該inode項已經在其中,則直

Lock並返回。只有此inode尚未讀入時,才需要從磁碟上讀取。

萊昂對此函式的講解比較詳細,在這裡我只說幾點:

(1)    在讀入該磁碟inode所在盤塊時,使用如下語句:

7319:     ip = bread(dev, ldiv(ino+31,16));

1)   indoe塊是從#2塊開始的(#0UNIX忽略不用、“超級塊”佔據了磁碟的#1塊);

2)   每個塊可容納16inode

(2)     在將磁碟inode內容複製給記憶體inode時,利用了二者自“i_mode”起layout相同的特點。

     因此,只需將指標指向磁碟inode頭,逐個位元組拷貝即可。如下所示:

7328:     ip1 = ip->b_addr + 32*lrem(ino+31, 1)

7329:     ip2 = &p->i_mode;

7330:     while(ip2 < &p->i_addr[8])

7331:          *ip2++ = *ip1++;

3)它會增加該inode的引用計數(i_count)。這也正是main()函式兩次呼叫它的原因,

       否則,在1618行,直接將rootdir賦值給u.u_cdir即可。程式碼如下所示:

0106: #define ROOTINO 1     //根目錄inode#1號磁碟inode

1616:     rootdir = iget(rootdev, ROOTINO);

1617:     rootdir->i_flag =& ~ILOCK;

1618:     u.u_cdir = iget(rootdev, ROOTINO);

1619:     u.u_cdir->i_flag =& ~ILOCK;

iput(p)函式用於釋放inode資源,它只有一個引數,即要釋放的inode。乍一想,這個函式應該很簡單,

iget的“逆”操作就可以了:

(1)         i_count減一;

(2)         ILOCK標誌

(3)         i_count變為0,則釋放其佔用inode陣列項。

但事實上,該函式要複雜的多:

(1)         程式在獲取inode資源後,可能因某種原因修改了inode

(2)         甚至可能需要刪除(檔案的硬連結i_nlink變為0inode所指向的物理檔案。

因此,這兩種情況也需要處理。理解了這些,這個函式就顯得很簡單了。

它內部還呼叫了其他幾個函式,介紹如下:

(1)         prele ——清除ILOCK標記,喚醒因此睡眠的程序;

(2)         iupdat ——將更新的inode寫入磁碟;

(3)         itrunc ——刪除檔案;

(4)         ifree ——回收inodefile system的空閒inode陣列(將來會談到)。