(萊昂氏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塊開始的(#0塊UNIX忽略不用、“超級塊”佔據了磁碟的#1塊);
2) 每個塊可容納16個inode
(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變為0)inode所指向的物理檔案。
因此,這兩種情況也需要處理。理解了這些,這個函式就顯得很簡單了。
它內部還呼叫了其他幾個函式,介紹如下:
(1) prele ——清除ILOCK標記,喚醒因此睡眠的程序;
(2) iupdat ——將更新的inode寫入磁碟;
(3) itrunc ——刪除檔案;
(4) ifree ——回收inode到file system的空閒inode陣列(將來會談到)。