Inode

**inode (index node)** 是指在許多「類 Unix 檔案系統」中的一種資料結構，用於描述檔案系統物件（包括檔案、目錄、裝置檔案、socket、管道等）。每個 inode 儲存了檔案系統物件資料的屬性和磁碟塊位置。檔案系統物件屬性包含了各種元資料（如：最後修改時間） ，也包含使用者群組（owner ）和權限資料。

## 命名

Unix 先驅丹尼斯・里奇說，inode 這個命名的來源可能是檔案系統的儲存組織為一個扁平陣列，分層目錄資訊使用一個數作為檔案系統這個扁平陣列的索引值（index）。

## 細節

檔案系統建立（格式化）時，就把儲存區域分為兩大連續的儲存區域。一個用來儲存檔案系統物件的元資訊資料，這是由 inode 組成的表，每個 inode 預設是 256 位元組或者 128 位元組。另一個用來儲存「檔案系統物件」的內容資料，劃分為 512 位元組的磁區，以及由 8 個磁區組成的 4K 位元組的塊。塊是讀寫時的基本單位。一個檔案系統的 inode 的總數一般情況下是固定的。這限制了該檔案系統所能儲存的檔案系統物件的總數目。典型的實現下，所有 inode 占用了檔案系統 1% 左右的儲存容量。

檔案系統中每個「檔案系統物件」對應一個「inode」資料，並用一個整數值來辨識。這個整數常被稱為 **inode 號碼**（「i-number」或「inode number」）。由於檔案系統的 inode 表的儲存位置、總條目數量都是固定的，因此可以用 inode 號碼去索引尋找 inode 表。

Inode 儲存了檔案系統物件的一些元資訊，如所有者、存取權限（讀、寫、執行）、類型（是檔案還是目錄）、內容修改時間、inode 修改時間、上次存取時間、對應的檔案系統儲存塊的位址，等等。知道了 1 個檔案的 inode 號碼，就可以在 inode 元資料中查出檔案內容資料的儲存位址。

檔名與目錄名是「檔案系統物件」便於使用的別名。一個檔案系統物件可以有多個別名，但只能有一個 inode，並用這個 inode 來索引檔案系統物件的儲存位置。

* inode 不包含檔名或目錄名的字串，只包含檔案或目錄的「元資訊」。
* Unix 的檔案系統的目錄也是一種檔案。打開目錄，實際上就是讀取「目錄檔案」。目錄檔案的結構是一系列**目錄項**（dirent）的列表。每個目錄項，由兩部分組成：所包含檔案或目錄的名字，以及該檔案或目錄名對應的 inode 號碼。
* 檔案系統中的一個檔案是指存放在其所屬目錄的「目錄檔案」中的一個目錄項，其所對應的 inode 的類別為「檔案」；檔案系統中的一個目錄是指存放在其「父目錄檔案」中的一個目錄項，其所對應的 inode 的類別為「目錄」。可見，多個「檔案」可以對應同一個 inode；多個「目錄」可以對應同一個 inode。
* 檔案系統中如果兩個檔案或者兩個目錄具有相同的 inode 號碼，那麼就稱它們是「硬連結」關係。實際上都是這個 inode 的別名。換句話說，一個 inode 對應的所有檔案（或目錄）中的每一個，都對應著檔案系統某個「目錄檔案」中唯一的一個目錄項。
* 建立一個目錄時，實際做了 3 件事：在其「父目錄檔案」中增加一個條目；分配一個 inode；再分配一個儲存塊，用來儲存當前被建立目錄包含的檔案與子目錄。被建立的「目錄檔案」中自動生成兩個子目錄的條目，名稱分別是：「.」和「..」。前者與該目錄具有相同的 inode 號碼，因此是該目錄的一個「硬連結」。後者的 inode 號碼就是該目錄的父目錄的 inode 號碼。所以，任何一個目錄的 "硬連結" 總數，總是等於它的子目錄總數（含隱藏目錄）加 2。即每個「子目錄檔案」中的「..」條目，加上它自身的「目錄檔案」中的「.」條目，再加上「父目錄檔案」中的對應該目錄的條目。
* 通過檔名打開檔案，實際上是分成三步實現：首先，作業系統找到這個檔名對應的 inode 號碼；其次，通過 inode 號碼，取得 inode 資訊；最後，根據 inode 資訊，找到檔案資料所在的 block，讀出資料。

Linux 系統使用 `struct inode` 作為資料結構名稱。BSD 衍生的系統，使用 `vnode` 名稱，其中 **v** 表示「virtual file system」。

## POSIX inode

POSIX 標準強制規範的檔案系統的行為受到傳統 UNIX 檔案系統的深刻影響。可以用短語「檔案序列號」來形容 inode，定義為_檔案系統範圍_的唯一檔案識別碼。上述的檔案序列號和包含此檔案的裝置 ID 一起，在整個系統上對應唯一的檔案。

在 POSIX 系統上，可使用 `stat` 系統呼叫取得檔案的下列屬性：

* 以位元組為單位表示的檔案大小。
* 裝置 ID，標識容納該檔案的裝置。
* 檔案所有者的 User ID。
* 檔案的 Group ID
* 檔案的模式（mode），確定了檔案的類型，以及它的所有者、它的 group、其它使用者存取此檔案的權限。
* 額外的系統與使用者標誌（flag），用來保護該檔案。
* 3 個時間戳，記錄了 inode 自身被修改（ctime, _inode change time_）、檔案內容被修改（mtime, _modification time_）、最後一次存取（atime, _access time_）的時間。
* 1 個連結數，表示有多少個硬連結指向此 inode。
* 到檔案系統儲存位置的指標。通常是 1K 位元組或者 2K 位元組的儲存容量為基本單位。

可以查詢一個檔案的 inode 號碼及一些元資訊。

## 推論

* 一個檔案系統物件可以有多個名字，這些具有硬連結關係的檔案系統物件名字具有相同的 inode 號碼，彼此是平等的。即首個被建立的檔案並沒有特殊的地位。這與符號連結不同。一個符號連結檔案有自己的 inode，符號連結檔案的內容是它所指向的檔案的名字。因此刪除符號連結所指向的檔案，將導致這個符號連結檔案在存取時報錯。
* 刪除一個檔案或目錄，實際上是把它的 inode 的連結數減 1。這並不影響指向此 inode 的別的硬連結。
* 一個 inode 如果沒有硬連結，此時 inode 的連結數為 0，檔案系統將回收該 inode 所指向的儲存塊，並回收該 inode 自身。
* 從一個 inode，通常是無法確定是用哪個檔名查到此 inode 號碼的。打開一個檔案後，作業系統實際上就拋掉了檔名，只保留了 inode 號碼來存取檔案的內容。函式庫函式 getcwd() 用來查詢當前工作目錄的絕對路徑名。其實現是從當前工作目錄的 inode 逐級尋找其上級目錄的 inode，最後拼出整個絕對路徑的名字。
* 歷史上，對目錄的硬連結是可能的。這可以使目錄結構成為一個有向圖，而不是通常的目錄樹的有向無環圖。一個目錄甚至可以是自身的父目錄。現代檔案系統一般禁止這些混淆狀態，只有根目錄保持了特例：根目錄是自身的父目錄。這項限制最著名的一個例外可在 Mac OS X（10.5 或更高版本）上找到：它允許超級使用者建立目錄的硬連結。
* 一個檔案或目錄在檔案系統內部移動時，其 inode 號碼不變。檔案系統碎片整理可能會改變一個檔案的物理儲存位置，但其 inode 號碼不變。非 UNIX 的 FAT 及其衍生的檔案系統是無法實現 inode 不變這一特點。
* inode 檔案系統中安裝新函式庫十分容易。當一些行程正在使用一個函式庫時，其它行程可以替換該函式庫檔案名字的 inode 號碼指向新建立的 inode，隨後對該函式庫的存取都被自動引導到新 inode 所指向的新的函式庫檔案的內容。這減少了替換函式庫時重新啟動系統的需要。而舊的 inode 的連結數已經為 0，在使用舊函式庫的行程結束後，舊的 inode 與舊函式庫檔案會被系統自動回收。
* 一些檔案系統，由於 inode 表在檔案系統建立時就已經確定並且不能再動態增加，新增的檔案數量可能會用盡 inode。這導致檔案系統還有空閒的儲存空間，但已經沒有空閒的 inode 可供使用了。例如，一個電子郵件伺服器可能會被大量的小檔案用盡所有 inode，但是卻沒有填滿檔案儲存空間。部分檔案系統，如 JFS 和 XFS，能夠動態地增加 inode，因此不會用盡 inode。

## 實際考慮

系統管理員使用的很多程式往往用 inode 號碼來替代檔名來存取檔案系統。例如磁碟完整性檢查程式 `fsck` 或 `pfiles`。因此，inode 號碼與檔案全路徑名的互查是需要的。可以用 `find` 帶參數選項 `-inum`，`ls` 帶參數選項 (`-i` 做到。

## 參考文獻

## 外部連結

* Anatomy Of The Linux File System（頁面存檔備份，存於網際網路檔案館）
* Inode definition （頁面存檔備份，存於網際網路檔案館）
* Great and Clear Explanation on Inodes, Symlinks, Hardlinks （頁面存檔備份，存於網際網路檔案館）
* 理解 inode （頁面存檔備份，存於網際網路檔案館）
* 一天一點學習 Linux 之 inode 詳解 （頁面存檔備份，存於網際網路檔案館）