Inode

inode（index node）是指在許多「類Unix文件系統」中的文件的資訊，每個inode保存了文件系統內的各個對象（包括文件、目錄、設備文件、socket、管道等）的數據的屬性和磁碟塊位置。這些數據包含了各種元數據（如：最後修改時間）。每當使用者創建一個文件，系統就會分配一個唯一的 inode號。它包含了文件類型（是普通文件、目錄還是連結）、權限（讀、寫、執行）、所有者和屬組（UID, GID）、文件大小、時間戳（創建、修改、最後訪問時間）等資訊。

## 命名

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

## 細節

<image>

文件系統創建（格式化）時，就把存儲區域分為兩大連續的存儲區域。一個用來保存文件系統對象的元資訊數據，這是由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詳解