什么是 inode ?
文件儲存在硬盤上,硬盤的最小存儲單位叫作”扇區”(Sector)。每一個扇區儲存512字節(至關於0.5KB)。
操作系統讀取硬盤的時候,不會一個個扇區地讀取,這樣效率過低,而是一次性連續讀取多個扇區,即一次性讀取一個”塊”(block)。這種由多個扇區組成的”塊”,是文件存取的最小單位。”塊”的大小,最多見的是4KB,即連續八個 sector組成一個 block。
文件數據都儲存在”塊”中,那么很顯然,咱們還必須找到一個地方儲存文件的元信息,好比文件的建立者、文件的建立日期、文件的大小等等。這種儲存文件元信息的區域就叫作inode,中文譯名為”索引節點”。每個文件都有對應的inode(數據結構里面應該叫inode節點),里面包含了與該文件有關的一些信息。由於每個文件都必須有一個inode,因此有可能發生inode已經用光,但是硬盤還未存滿的情況。這時,就無法在硬盤上創建新文件(一個inode由inode number+inode table組成)。
我們簡單理解就是一個文件對應一個inode,而linux各個分區可用的inode一般是有限的,使用df -i 可以查看分區的inode使用率。一般經常出現硬盤空間沒占滿,但inode占滿了,這種一般是因為有大量的小文件生成, 在Linux中創建文件系統時,通常同時將會創建大量的inode,文件系統磁盤空間中大約百分之一空間分配給了inode表。在每個Linux存儲設備或存儲設備的分區(存儲設備可以是硬盤、軟盤、U盤…)被格式化為ext4、ext3、xfs等文件系統,一般生成兩部分:第一部分是Inode(很多個),第二部分是Block(很多個)。
當我們使用cp命令時,系統會分配一個空閑的inode號,在inode表中生成新條目 在目錄中創建一個目錄項,將名稱與inode編號關聯 拷貝數據生成新的文件
當我們使用rm命令時,會使鏈接數遞減,從而釋放的inode號可以被重用,把數據塊放在空閑列表中,刪除目錄項數據實際上不會馬上被刪除,但當另一個文件使用數據塊時將被覆蓋。
當我們使用mv命令時,如果mv命令的目標和源在相同的文件系統,作為mv命令,用新的文件名創建對應新的目錄項,刪除舊目錄條目對應的舊的文件名,不影響inode表(除時間戳)或磁盤上的數據位置,沒有數據被移動!如果目標和源在一個不同的文件系統,mv相當於cp和rm
關於inode的大小
假定在一塊1GB的硬盤中,每個inode節點的大小為128字節,每1KB就設置一個inode,那么inode table的大小就會達到128MB,占整塊硬盤的12.8%。(計算inode的節點數量和占據的大小)
關於inode號碼(inode number)
每個inode都有一個號碼,操作系統用inode號碼來識別不同的文件,Unix/Linux系統內部不使用文件名,而使用inode號碼來識別文件。對於系統來說,文件名只是inode number便於識別的別稱或者綽號。表面上,用戶通過文件名,打開文件。實際上,系統內部這個過程分成三步:首先,系統找到這個文件名對應的inode號碼;其次,通過inode號碼,獲取inode信息;最后,根據inode信息,找到文件數據所在的block,讀出數據。當一個分區被格式化為ext2或ext3的文件系統的時候,會自動產生inode number,每個分區都有自己的文件系統,也有一套屬於自己的inode。inode number可以決定在這個分區中存儲多少文件或目錄,因為每個文件和目錄都會有與之相對應的inode number。
元數據(metadata):用來描述一個文件的特征的系統數據。
我們也把inode區叫inode table,即inode table用於儲存文件元信息的區域。inode table記錄這個inode number對應文件所對應的metadata(元數據)。
舉例:

當你存儲一個文件之前,Linux系統會找到文件所對應的inode number。然后根據這個文件的inode number讀取到相對應的inode table。由inode table中的“pointer”可以知道文件存放在哪幾個block才能存儲這個文件。(這里是數據結構了)
注: 以后我們說磁盤滿了,就不要單單說數據被占滿了,而是inode有可能滿了,導致文件創建不成功。有時候用df -h查看空間並沒有滿,但是寫不進去東西了,就可能是inode數量被消耗殆盡了。
下面這張圖還是很說明問題
系統環境采樣:
[root@fp-web-130 ~]# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[root@fp-web-130 ~]# uname -r
3.10.0-327.el7.x86_64
一、用df -i 這個命令可以看到文件系統 inode節點數 已使用數 剩余數 已使用百分比等
[root@fp-web-130 ~]# df -i
二、使用stat命令查看文件inode詳細信息(顯示文件和文件系統狀態(查看文件屬性),即顯示文件的元數據(meta data) )
我們隨便拿個創建的文件看下怎么使用(另外stat * 命令直接顯示該目錄下所有文件的信息)
解釋stat結果說明:
File:文件名
Size:文件大小(單位:B)
Blocks:文件所占扇區個數,為8的倍數(通常的 Linux 的扇區大小為 512 B,連續八個扇區組成一個block)
IO Block:每個數據塊的大小(單位:B)
regular file:普通文件(此處顯示文件的類型)
Inode:文件的Inode號 ( node講解 )
Links:硬鏈接次數 (軟硬鏈接講解)
Access:權限
Uid:(屬主id/屬主名)
Gid:(屬組id/屬組名)
Access:最近訪問時間
Modify:數據改動時間
Change:元數據改動時間
以上返回的結果參數均屬於文件的元數據,元數據即用來描述數據的數據。
注: Inode:270219136 和下面的用ls -i 取得的inode號一致。
三、使用ls -i //查看某個文件的inode號
四、關於linux不能再創建文件有兩種情況
1、inode滿了,沒有清理 ,可以通過df -i 查看
2、磁盤的空間滿了,可以通過 df -h查看
五、查看inode默認節點大小
我們看到用不同文件類型方式創建了文件系統,有xfs,lvm,ext3等
[root@fp-web-130 ~]# dumpe2fs /dev/sdb5 | grep -i "inode size" //該命令用於查看ext3或ext4文件類型的inode節點默認創建的大小
[root@fp-web-130 ~]# dumpe2fs /dev/sda1|egrep -i "block size|Inode size" //我們同樣用這個命令來查看xfs會出錯,dumpe2fs 不支持
所以我們使用 xfs_info 或 xfs_growfs來查看xfs文件格式的inode默認創建的大小(super-block我們翻譯為超級塊)
[root@fp-web-130 ~]# xfs_info /dev/sda1
六、可以用inode刪除文件(linux系統級別是通過inode號來查找文件的,所以效率更高)
[root@fp-web-130 src]# touch test.txt
[root@fp-web-130 src]# ll -i test.txt
330651 -rw-r--r-- 1 root root 0 Feb 8 22:11 a
[root@fp-web-130 src]# rm `find . -inum 330651`
rm: remove regular empty file ‘./text.txt’? yes
[root@fp-web-130 src]# ll
total 0
七、超級塊(super-block)
超級塊用於存儲一個已安裝的文件系統全局配置參數(例如:塊大小,總的塊數和inode)和動態信息(例如:當前空閑塊數和inode數),其處於文件系統開始位置的1K處,所占大小為1KB,為了系統的健壯性,最初每個塊組都有超級塊和組描述符表(GDT)一個拷貝,但是當文件很大時,這樣浪費很多塊(尤其是GDT占用的塊多),后來采用了一種稀疏的方式存儲這些拷貝,只有快組號是3,5,7的冪的塊組才拷貝這個拷貝。通常情況下,只有主拷貝(第0塊塊組)的超級塊信息被文件系統使用,其他拷貝在文件系統被破壞的情況下才使用
八、理解下inode結構體
先看inode結構體的定義,inode 結構包含大量關於文件的信息,inode 結構由內核在內部用來表示文件
struct inode
索引節點對象由inode結構體表示,定義文件在linux/fs.h中。
struct inode {
undefined
struct hlist_node i_hash; 哈希表
struct list_head i_list; 索引節點鏈表
struct list_head i_dentry; 目錄項鏈表
unsigned long i_ino; 節點號
atomic_t i_count; 引用記數
umode_t i_mode; 訪問權限控制
unsigned int i_nlink; 硬鏈接數
uid_t i_uid; 使用者id
gid_t i_gid; 使用者id組
kdev_t i_rdev; 實設備標識符
loff_t i_size; 以字節為單位的文件大小
struct timespec i_atime; 最后訪問時間
struct timespec i_mtime; 最后修改(modify)時間
struct timespec i_ctime; 最后改變(change)時間
unsigned int i_blkbits; 以位為單位的塊大小
unsigned long i_blksize; 以字節為單位的塊大小
unsigned long i_version; 版本號
unsigned long i_blocks; 文件的塊數
unsigned short i_bytes; 使用的字節數
spinlock_t i_lock; 自旋鎖
struct rw_semaphore i_alloc_sem; 索引節點信號量
struct inode_operations *i_op; 索引節點操作表
struct file_operations *i_fop; 默認的索引節點操作
struct super_block *i_sb; 相關的超級塊
struct file_lock *i_flock; 文件鎖鏈表
struct address_space *i_mapping; 相關的地址映射
struct address_space i_data; 設備地址映射
struct dquot *i_dquot[MAXQUOTAS];節點的磁盤限額
struct list_head i_devices; 塊設備鏈表
struct pipe_inode_info *i_pipe; 管道信息
struct block_device *i_bdev; 塊設備驅動
unsigned long i_dnotify_mask;目錄通知掩碼
struct dnotify_struct *i_dnotify; 目錄通知
unsigned long i_state; 狀態標志
unsigned long dirtied_when;首次修改時間
unsigned int i_flags; 文件系統標志
unsigned char i_sock; 套接字
atomic_t i_writecount; 寫者記數
void *i_security; 安全模塊
__u32 i_generation; 索引節點版本號
union {
undefined
void *generic_ip;文件特殊信息
} u;
};
九、文件描述符(區別於inode)
inode 或i節點是指對文件的索引。如一個系統,所有文件是放在磁盤或flash上,就要編個目錄來說明每個文件在什么地方,有什么屬性,及大小等。就像書本的目錄一樣,便於查找和管理。這目錄是操作系統需要的,用來找文件或叫管理文件。許多操作系統都用到這個概念,如linux, 某些嵌入式文件系統等。當然,對某個系統來說,有許多i節點。所以對i節點本身也是要進行管理的。
在linux中,內核通過inode來找到每個文件,但一個文件可以被許多用戶同時打開或一個用戶同時打開多次。這就有一個問題,如何管理文件的當前位移量,因為可能每個用戶打開文件后進行的操作都不一樣,這樣文件位移量也不同,當然還有其他的一些問題。所以linux又搞了一個文件描述符(file descriptor)這個東西,來分別為每一個用戶服務。每個用戶每次打開一個文件,就產生一個文件描述符,多次打開就產生多個文件描述符,一一對應,不管是同一個用戶,還是多個用戶。該文件描述符就記錄了當前打開的文件的偏移量等數據。所以一個i節點可以有0個或多個文件描述符。多個文件描述符可以對應一個i節點。