1. 程式人生 > >關於檔案的INode與Java中的檔案操作介面

關於檔案的INode與Java中的檔案操作介面

本文由作者周樑偉授權網易雲社群釋出。


近日做的專案中涉及到多程序共同讀寫多個檔案的問題,檔名和最後修改時間都是可能會被頻繁修改的,因而識別檔案的唯一性會產生相當的麻煩,於是專門再學習了一下檔案系統對檔案的組織管理方式。

一、    檔案在檔案系統中的組織方式

一塊物理磁碟可以被分為若干個分割槽,分割槽的初始化操作就是在上面建立檔案系統,如ext3,ext4,ntfs或fat32等都是檔案系統的概念,還有網路檔案系統如NFS等。同塊磁碟上的不同分割槽也可以被指定不同的檔案系統,檔案系統對檔案在磁碟上的資料讀寫方式做了抽象。一個檔案系統中又被分為多個卷(Cylinder Group),每個卷中最主要的部分是inode基路段和資料塊段。i-node結構唯一指定了一個檔案例項,這個資料結構中包括了inode編號,所有包含的資料塊的資訊和該inode被引用的計數等。可以這麼認為,要唯一識別的一個磁碟上的檔案,只需要獲得inode-number就可以了。檔案或者目錄則是存放在資料塊中directory block,其中包含了檔名和實體檔案的inode-number等資訊。檔名是可以隨時被改變的,只要其中的inode-number沒有發生改變,則指向的就是同一個檔案。所以在應用程式中要判斷檔案是否相同如果依靠filename是不可靠的,只有獲取到檔案的inode-number才是可靠的。如在log4j這種日誌應用中,日誌檔案的歸檔方式會使檔名不斷髮生變化,當前你less到的app.log在下一分鐘可能就變成了app.log.1。在這種場景下,程式只能通過獲取檔案inode-number來識別檔案。

二、    檔案操作

前面說了檔案在磁碟上的存放是以inode-number為唯一id來區分的,在程序開啟一個檔案讀寫時,作業系統又會為檔案分配一個"指標"來訪問檔案,而不是直接使用inode-number。這個指標就是FileDescriptor(下面簡稱FD),FD是一個動態的概念,是程序中呼叫create後open檔案操作是返回的一個Long值,當檔案關閉時這個FD也就失效了,所以同一個檔案如果被開啟兩次獲取到的FD會是不同的。程序開啟檔案的情況如下圖所示,在程序中維護了一張表記錄所有開啟的檔案,每一條記錄表示一個FileDescriptor,每個程序在開始時都預設打開了三個檔案,FileDescriptor分別是0,1,2,既stdin, stdout和stderr。FD記錄中包含了一張FileTable,記錄了檔案的狀態資訊,offset和V-node指標,V-Node指標才真正指向了磁碟上的檔案實體。(這裡的V-Node是在inode之上抽象出來的概念,因為i-node在不同的檔案系統中會有實現上的差異,V-Node是為了統一不同檔案系統的介面抽象出來的一層,在Linux中V-Node被稱為 FileSystem independent INode ,而INode 稱為FileSystem dependent Inode,我們可以簡單的理解為 V-Node就是INode)。

當一個檔案被多個程序共享讀寫時,可以看如下圖:

這裡程序A的fd3和程序B的fd4其實指向的是同一個實體檔案,但是這兩個程序維護了兩張不同的檔案表,維護了不同的offset位置。所以如果程序不是採用append方式寫檔案,兩個程序寫入的內容可能出現相互覆蓋。這裡也可能看到雖然FD不同,但是可以指向同一個實體檔案,也說明了用FD來判斷檔案唯一性是不靠譜的。
關於FD和INode,還有關於快取的重要注意事項。
由於作業系統在接收到檔案寫請求時可能將寫入內容放到快取中,所以提供了flush和sync等操作來將快取中的內容強制刷入磁碟。但是這兩個操作作用是不同的。
flush會將資料刷入到FileDescriptor中,但是不會刷入Inode
sync/fsync/fdatasync則會強制將FD中的資料刷入Inode中。

三、    Java操作檔案的介面

最後需要注意的一點是,雖然在檔案的存續期間,inode可以認為是識別該檔案的唯一標識,但是檔案系統對inode有回收重用的機制,在檔案被刪除之後,原來的inode可以被分配給新建立的檔案,這種情況下,如果一味以inode相同來判定新舊檔案是不是同一個檔案可能會出現錯誤;應對這種情況確實也沒有更好的辦法,一種解決方法是,提取檔案中部分內容的MD5或SHA-1這種指紋資訊作為標識,以inode+md5是否相同來決定是否是同個檔案。



免費領取驗證碼、內容安全、簡訊傳送、直播點播體驗包及雲伺服器等套餐

更多網易技術、產品、運營經驗分享請訪問網易雲社群

相關文章:
【推薦】 Message Loop 原理及應用