41-18 Linux目錄與inode 深入理解

1、關於Linux目錄,文件,數據塊
對於使用計算機的人而言,經常有一種 錯誤的認知:目錄(或者說,文件夾)裏面存放着文件。實際上,目錄裏面並不存放文件,以及文件數據。
實際上,目錄是一個特殊的文件,針對這個特殊的文件也存在一些特殊的規則,比如利用命令cp /dev/null 並不能夠銷燬這個特殊的文件,因爲目錄的一些特殊的比特位保證了這一安全性,降低了人工操作帶來的風險。在一些老版本的Unix系統裏面,用戶可以利用cat命令打開目錄,查看裏面的信息,在一些衍生於Debian系統的發行版Linux裏面,也可以利用vi工具打開目錄,查看一些信息。
在Linux裏面,一個文件的信息被存放於兩個位置:
1. 數據塊(data block)當中
2. inode當中

硬盤的最小存儲單位叫做“扇區”(Sector)。每個扇區儲存512字節(相當於0.5KB)。操作系統讀取磁盤的時候,不會一個個扇區“挨個讀取”,而是一次讀取多個扇區,即一次讀取一個“塊”(block),這種由多個扇區組成的”塊”,是文件存取的最小單位。”塊”的大小,最常見的是4KB,即連續八個 sector組成一個 block。data block當中存放了文件的真實內容,而文件的元數據信息,被存放到了inode當中。data block和inode被文件系統有效地組織到了一起。
當文件系統被創建之後,inode的數量以及data block的數量也被固定下來。我們不能夠修改inode的數量,也不能夠修改data block的數量。
當我們創建一個文件的時候,inode編號將作爲該文件的唯一id,即,一個文件在同一時刻僅擁有一個inode編號。當我們向一個文件寫入內容的時候,數據被存放到了data block當中。而該文件的文件名,被存放到了該文件所在的目錄文件當中。
對於目錄這種“特殊的文件”,可以簡單地理解爲是一張表,這張表裏面存放了隸屬於該目錄的文件的文件名,以及所匹配的inode編號。
因此,在linux裏面,文件被“拆分”到了3個地方,索引存於inode,文件名存於目錄,數據存於data block。

2、關於硬鏈接以及複製
基於上述內容對於目錄的描述,可以比較容易解釋linux裏面的另外一個重要的概念: hard link(硬鏈接)。
對於文件而言,真正的ID是inode編號,而並非文件名。回憶一下目錄文件: 一張含有文件名和inode編號的表。在這張表裏面,我們暫定用一個如下結構表示一個文件: [directory : (filename, inode_number)],這裏以/etc/passwd文件舉例,假設其inode編號爲123456(確實有點兒假……),則可以寫爲[/etc/ : (passwd, 123456)],假設我們在終端上面鍵入瞭如下命令:
[root@CentOS7-front1 ~]# ln /etc/passwd /root/hard_link_passwd
則會在/root目錄下面出現一個新的文件名,叫做hard_link_passwd。如果用上述結構表示這個文件,則爲[/root/ : (hard_link_passwd, 123456)],因此,這種目錄或文件名不同,但是inode編號相同的文件,稱爲硬鏈接。由於硬鏈接inode編號相同,而且對於同一個inode結構體,便會擁有相同的地址映射以及相同的塊設備鏈表。因此,對於用戶空間而言,修改/etc/passwd,就相當於修改了/root/hard_link_passwd,反之亦然。

同樣基於上述內容對於目錄的描述,針對i_device相同的mv操作,僅僅是刪除了原目錄裏面對應的[directory : (filename, inode_number)],並且在目標目錄新建了另一個[directory : (filename, inode_number)],由於並沒有對於data block的任何操作,因此速度很快。

3、初步查看inode
利用ls -i命令可以查看到當前目錄下面的所有文件的inode編號,注意inode編號僅僅是inode結構體裏面的一項,並不代表inode全部,下面截取/etc/目錄下的前5個文件:
[root@centos7-front1 etc]# ls -i | head -n 5
768684 abrt
34370879 adjtime
33554592 aliases
35506331 aliases.db
100705463 alternatives

利用stat命令可以查看一個文件更加詳細的inode信息,包括inode編號,佔用的塊數量,塊大小,硬鏈接個數,atime, mtime, ctime, ……下面用stat命令查看/etc目錄(如上文所說,目錄也是一種特殊的文件)
[root@centos7-front1 /]# stat /etc
File: ‘/etc’
Size: 8192 Blocks: 24 IO Block: 4096 directory
Device: 803h/2051d Inode: 33554561 Links: 85
Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2017-03-28 17:13:00.510221799 -0400
Modify: 2017-03-28 12:37:32.150999451 -0400
Change: 2017-03-28 12:37:32.150999451 -0400
Birth: -

從上述結果中,我們可以看出,針對/etc目錄而言,其大小爲8192kb,爲該目錄下的文件所分配的塊數量爲24個,類型爲directory,設備名稱爲803h/2051d,其Inode編號爲33554561,其硬鏈接個數爲85個,權限爲0755,Uid和Gid均爲0,還有atime, mtime, ctime這些信息。
當然,利用stat命令查到的某個文件的inode信息並不是全部的inode結構體裏面的信息。內核使用的inode結構體如下所示:
struct inode {
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 {
void *generic_ip; // 文件特殊信息 */
} u;
};

4、inode使用情況以及大小
inode也會消耗硬盤空間,所以硬盤格式化的時候,操作系統自動將硬盤分成兩個區域。一個是數據區,存放文件數據;另一個是inode區(inode table),存放inode所包含的信息。
每個inode節點的大小,一般是128字節或256字節。inode節點的總數,在格式化時就給定,一般是每1KB或每2KB就設置一個inode。假定在一塊1GB的硬盤中,每個inode節點的大小爲128字節,每1KB就設置一個inode,那麼inode table的大小就會達到128MB,佔整塊硬盤的12.8%。
查看每個硬盤分區的inode總數和已經使用的數量,可以使用df命令。
[root@centos7-front1 ~]# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 23860224 59694 23800530 1% /
devtmpfs 122809 367 122442 1% /dev
tmpfs 125170 1 125169 1% /dev/shm
tmpfs 125170 433 124737 1% /run
tmpfs 125170 13 125157 1% /sys/fs/cgroup
/dev/sda1 256000 329 255671 1% /boot
tmpfs 125170 1 125169 1% /run/user/0

查看某個分區的文件系統所分配的單個inode節點的大小,在ext文件系統下,可以使用dumpe2fs命令,例如CentOS6系統上,針對/dev/sda3分區:
[root@maCentos6 ~]# dumpe2fs -h /dev/sda3 | grep -i “inode size”
dumpe2fs 1.41.12 (17-May-2010)
Inode size: 256

在xfs文件系統下,可以使用xfs_info命令,例如CentOS7系統上,針對/dev/sda3分區:
[root@centos7-front1 ~]# xfs_info /dev/sda1
meta-data=/dev/sda1 isize=256 agcount=4, agsize=16000 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0
data = bsize=4096 blocks=64000, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal bsize=4096 blocks=853, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0

linux公社

發佈了114 篇原創文章 · 獲贊 20 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章