理解文件系統
????????我們知道文件可以分為磁盤文件和內存文件,內存文件前面我們已經談過了,下面我們來談談磁盤文件。
目錄
一、引入"塊"概念
解析?stat demo.c?命令輸出
基本信息
設備信息
索引節點信息
權限信息
時間戳
二、引入"分區"概念
1、在Linux系統中,可通過以下命令查看磁盤分區信息
2、磁盤實現分區
3、磁盤格式化
三、引入"inode"概念
解析?ls -l?命令輸出內容
各字段詳細解析
特殊情況的表示
解析?ls -li?命令輸出
Inode號 (第1列)
注意
請注意
目前大家可能還存在兩個疑問
一、引入"塊"概念
????????硬盤是典型的"塊"設備。操作系統在讀取硬盤數據時,并非逐個扇區讀取(這樣效率太低),而是通過一次性連續讀取多個扇區來實現,這個連續讀取的單位稱為"塊"(block)。
????????每個硬盤分區都被劃分為若干個"塊"。"塊"的大小在格式化時確定且不可更改,最常見的大小是4KB(即連續八個扇區組成一個"塊")。"塊"是文件存取的最小單位。
stat 文件名
解析?stat demo.c
?命令輸出
stat
?命令用于顯示文件或文件系統的詳細狀態信息。以下是?demo.c
?文件的詳細信息解析:
基本信息
-
文件名: 'demo.c'
-
大小: 182 字節
-
占用塊數: 8 個塊 (通常每個塊512字節,所以占用約4KB空間)
-
IO塊大小: 4096 字節 (文件系統塊大小)
-
類型: 普通文件 (regular file)
設備信息
-
設備號: fd01h/64769d (主設備號fd01h,次設備號64769d)
索引節點信息
-
Inode號: 655967
-
硬鏈接數: 1 (表示沒有其他硬鏈接指向此文件)
權限信息
-
訪問權限: 0664 (-rw-rw-r--)
-
所有者(hmz): 讀寫權限(rw-)
-
所屬組(hmz): 讀寫權限(rw-)
-
其他用戶: 只讀權限(r--)
-
-
所有者: UID 1000 (用戶名hmz)
-
所屬組: GID 1000 (組名hmz)
時間戳
-
最后訪問時間(Access): 2025-07-16 23:18:34.624613705 +0800
-
最后修改時間(Modify): 2025-07-16 23:18:26.954651585 +0800 (文件內容最后修改時間)
-
最后狀態變更時間(Change): 2025-07-16 23:18:26.955651450 +0800 (文件元數據如權限等最后變更時間)
-
創建時間(Birth): - (不支持或未記錄)
注意:
- 磁盤可視為一個三維數組,我們將其抽象為一維數組處理,數組下標對應LBA(Logical Block Address),每個元素代表一個扇區
- 每個扇區都有對應的LBA地址,8個扇區組成一個塊,可以根據LBA計算出塊地址
- LBA與塊號的轉換關系:
- 已知LBA求塊號:塊號 = LBA / 8
- 已知塊號求LBA:LBA = 塊號 * 8 + n(n表示塊內扇區序號)
二、引入"分區"概念
????????磁盤作為典型的塊設備,通常以512字節的扇區為基本單位。以512GB磁盤為例,其包含超過十億個扇區。
????????實際上,磁盤可以被劃分為多個分區(partition)。分區編輯器將磁盤劃分為若干邏輯區域,不同分區可存儲特定類型的目錄和文件。分區越多,文件分類管理就越細致。以Windows系統為例,你可能有一塊物理磁盤并將其劃分為C、D、E盤,這些盤符就代表不同的分區。從本質上說,分區就是對硬盤進行格式化的一種方式。
1、在Linux系統中,可通過以下命令查看磁盤分區信息
ls /dev/vda* -l
2、磁盤實現分區
????????在Linux系統中,所有設備都以文件形式存在,那么如何實現分區呢?分區的最小單位是柱面,我們可以通過指定柱面編號來進行分區,具體操作就是設置每個分區的起始和結束柱面編號。
????????為了更直觀地理解,我們可以將硬盤上的柱面(分區)展開,想象成一個平面示意圖,如下圖所示:
注意:
當滿足以下條件時:
-
所有柱面大小一致(即每個柱面包含相同數量的磁道)
-
每個磁道的扇區數相同(即"扇區個位一致")
那么計算分區大小和LBA地址可以簡化為:
-
分區大小計算:
分區大小 = (結束柱面號 - 起始柱面號 + 1) × 每柱面扇區數 × 扇區大小 -
LBA計算:
某位置的LBA = 起始柱面的LBA + (柱面偏移 × 每柱面扇區數) + 磁頭偏移 × 每磁道扇區數 + 扇區偏移 - 1
3、磁盤格式化
????????在完成磁盤分區后,還需要進行格式化操作。格式化是對磁盤分區進行初始化的過程,這一操作會清除分區內所有現有文件。
簡而言之,格式化就是在各個分區中寫入相應的管理信息。
????????其中,寫入的管理信息是什么是由文件系統決定的,不同的文件系統格式化時寫入的管理信息是不同的,常見的文件系統有EXT2、EXT3、XFS、NTFS等。 會在后面的博客中進行講解!
三、引入"inode"概念
????????在Linux系統中,文件內容與元數據是分開存儲的。這種存儲元數據的結構稱為inode。由于系統中可能存在大量文件,每個文件屬性集都需要一個唯一標識符,即inode編號。
????????簡而言之,inode就是文件屬性的集合。Linux系統中幾乎所有文件都擁有自己的inode。為了有效區分系統中的眾多inode,每個inode都被分配了唯一的編號。
????????正如之前所述,文件由數據和屬性兩部分組成。當我們使用ls -l
命令時,不僅能看到文件名,還能查看文件的元數據(即屬性信息)。
ls -l
解析?ls -l
?命令輸出內容
? ? ls -l
?是 Linux/Unix 系統中常用的命令,用于以長格式顯示文件和目錄的詳細信息。以下是典型輸出的解析:
各字段詳細解析
-
文件類型和權限(第1列)
由10個字符組成,例如?-rwxr-xr--
:-
第1個字符:文件類型
標識符 文件類型 說明 -
普通文件 常規文件,如文本、二進制文件等 d
目錄 文件夾,包含其他文件或子目錄 l
符號鏈接 快捷方式,指向另一個文件或目錄(如? link -> target
)c
字符設備文件 按字符流訪問的設備(如終端? /dev/tty
)b
塊設備文件 按數據塊訪問的設備(如硬盤? /dev/sda
)s
套接字文件 進程間通信的套接字文件(如 MySQL 的? /var/run/mysqld/mysqld.sock
)p
命名管道文件 先進先出(FIFO)管道,用于進程間通信(如? mkfifo
?創建的文件) -
第2-4字符:所有者權限(u)
-
第5-7字符:組權限(g)
-
第8-10字符:其他用戶權限(o)
-
權限字符:
字符 權限類型 說明 r
讀權限 允許查看文件內容(文件)或列出目錄內容(目錄) w
寫權限 允許修改文件內容(文件)或在目錄中創建/刪除文件(目錄) x
執行權限 允許執行文件(程序/腳本)或進入目錄(目錄) s
SUID/SGID SUID(所有者位置):以文件所有者權限執行
SGID(組位置):以文件所屬組權限執行或繼承父目錄的組權限t
粘滯位 僅對目錄有效,用戶只能刪除自己擁有的文件(如? /tmp
?目錄)
-
-
硬鏈接數(第2列)
顯示指向該文件/目錄的硬鏈接數量。目錄通常至少有2個鏈接(自身和.
)。 -
所有者(第3列)
文件/目錄的屬主用戶名。 -
所屬組(第4列)
文件/目錄的屬組名。 -
大小(第5列)
-
普通文件:顯示字節大小
-
目錄:顯示目錄元數據占用的空間(通常4096字節)
-
-
最后修改時間(第6-8列)
顯示文件/目錄的最后修改時間,格式通常為:-
月份(如Jun)
-
日期(如12)
-
時間(如14:30)
-
如果文件修改時間超過6個月,會顯示年份而非時間
-
-
文件名(最后一列)
文件或目錄名稱。如果是符號鏈接,會顯示?linkname -> targetname
。
特殊情況的表示
-
SUID/SGID權限:
-
rwsr-xr-x
(所有者x位置變為s表示SUID) -
rwxr-sr-x
(組x位置變為s表示SGID)
-
-
粘滯位:
-
rwxr-xr-t
(其他用戶x位置變為t)
-
-
大小時單位顯示:
使用?-lh
?選項時會以K/M/G等易讀單位顯示大小
ls -l
用于讀取磁盤上的文件信息并顯示詳細列表:
除了通過這種方式讀取信息,還可以使用 stat 命令查看更詳細的內容:
????????這里我們需要思考一個問題:既然文件數據都存儲在"塊"中,那么顯然還需要一個地方來存儲文件的元信息(屬性信息),比如創建者、創建日期、文件大小等。這個存儲文件元信息的區域就叫做inode,中文譯名為"索引節點"。
ls -li
解析?ls -li
?命令輸出
? ? ls -li
?命令結合了?-i
?(顯示inode號) 和?-l
?(長格式) 選項,提供比普通?ls -l
?更詳細的信息。以下是完整解析:
Inode號 (第1列)
-
唯一標識文件系統內的文件
-
示例:
1234567
-
特點:
-
每個文件/目錄有唯一inode號
-
硬鏈接共享相同inode號
-
刪除文件實際上是減少inode的鏈接計數
-
????????每個文件都對應一個inode,其中存儲著該文件的相關信息。要理解inode的概念,我們需要先深入了解文件系統的工作原理。
注意
- Linux系統中文件采用屬性與內容分離的存儲機制
- Linux通過inode結構存儲文件屬性,每個文件對應一個獨立的inode
- inode中包含唯一的標識符,稱為inode號
一個文件的 inode 屬性具體是什么樣呢?我們來到源碼中看看對應的結構:
/** Structure of an inode on the disk (ext2文件系統的磁盤inode結構)*/
struct ext2_inode {/* 基礎信息 */__le16 i_mode; /* 文件類型和權限 (rwx) */__le16 i_uid; /* 所有者UID低16位 */__le32 i_size; /* 文件大小(字節) *//* 時間戳(Unix時間戳格式) */__le32 i_atime; /* 最后訪問時間 */__le32 i_ctime; /* 創建時間 */__le32 i_mtime; /* 最后修改時間 */__le32 i_dtime; /* 刪除時間 *//* 所有權信息 */__le16 i_gid; /* 所屬組GID低16位 */__le16 i_links_count; /* 硬鏈接計數 */__le32 i_blocks; /* 占用塊數(512字節為單位) */__le32 i_flags; /* 文件標志(如不可修改、壓縮等) *//* 操作系統特定數據1 */union {struct {__le32 l_i_reserved1;} linux1;struct {__le32 h_i_translator;} hurd1;struct {__le32 m_i_reserved1;} masix1;} osd1;/* 數據塊指針 */__le32 i_block[EXT2_N_BLOCKS]; /* 直接/間接塊指針(共15個) *//* 擴展屬性 */__le32 i_generation; /* 文件版本(用于NFS) */__le32 i_file_acl; /* 文件ACL塊指針 */__le32 i_dir_acl; /* 目錄ACL塊指針 */__le32 i_faddr; /* 碎片地址 *//* 操作系統特定數據2 */union {struct {__u8 l_i_frag; /* 碎片編號 */__u8 l_i_fsize; /* 碎片大小 */__u16 i_pad1;__le16 l_i_uid_high; /* 所有者UID高16位 */__le16 l_i_gid_high; /* 所屬組GID高16位 */__u32 l_i_reserved2;} linux2;struct {__u8 h_i_frag;__u8 h_i_fsize;__le16 h_i_mode_high;__le16 h_i_uid_high;__le16 h_i_gid_high;__le32 h_i_author;} hurd2;struct {__u8 m_i_frag;__u8 m_i_fsize;__u16 m_pad1;__u32 m_i_reserved2[2];} masix2;} osd2;
};/** 數據塊相關常量*/
#define EXT2_NDIR_BLOCKS 12 /* 直接塊數量 */
#define EXT2_IND_BLOCK (EXT2_NDIR_BLOCKS) /* 一級間接塊索引 */
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) /* 二級間接塊索引 */
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) /* 三級間接塊索引 */
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) /* 總塊指針數(15個) */
查看源碼后,我們可以知道inode這個數據結構中包含了很多很多的文件屬性!!!
請注意
- 文件名屬性不包含在inode數據結構中
- inode大小通常為128字節或256字節,后續討論中將統一采用128字節
- 不同文件的內容大小可以各不相同,但其屬性大小始終相同
目前大家可能還存在兩個疑問
-
我們已經知道硬盤是典型的"塊"設備,操作系統讀取硬盤數據的基本單位是"塊"。這些"塊"作為硬盤分區下的結構,它們是如何在分區上有序分布的?系統又是如何快速定位到這些"塊"的呢?
-
前面提到的存儲文件屬性的inode,它們又是如何被組織存放的?
文件系統正是為了解決這些問題而設計的!后面將會講解文件系統的相關知識!!!