系统块大小(block size)

时间:2021-02-03 05:15:33

系统块大小,block size并不被重视,因为一般很少会注视到,除非需要探究文件系统原理。df命令源码实现

涉及库函数如下:

int statfs(const char *path, struct statfs *buf);
int fstatfs(int fd, struct statfs *buf);
 
参数:
path: 位于需要查询信息的文件系统的文件路径名。
fd: 位于需要查询信息的文件系统的文件描述词。
buf:以下结构体的指针变量,用于储存文件系统相关的信息
 
struct statfs {
long f_type; /* 文件系统类型 */
long f_bsize; /* 经过优化的传输块大小 */
long f_blocks; /* 文件系统数据块总数 */
long f_bfree; /* 可用块数 */
long f_bavail; /* 非超级用户可获取的块数 */
long f_files; /* 文件结点总数 */
long f_ffree; /* 可用文件结点数 */
fsid_t f_fsid; /* 文件系统标识 */
long f_namelen; /* 文件名的最大长度 */
};

结构体 statfs中存有可用块数大小,因此计算空间剩余字节数需获得该系统块大小。

文件系统块(Block)

block即文件系统格式化后的分区的最小单位,其大小在格式化时被指定,一般为1KB,2KB,4KB磁盘分区只有被文件系统格式化之后才能被操作系统使用。硬盘最小存储单位是sector即扇区,为了增加读写效率则有了逻辑区块( Block )这个概念,其为sector的2次方倍数。

注意:文件系统创建时系统块大小就已确定,一般创建文件系统之后就无法更改。

文件系统块大小查询

在linux系统上,可以用命令tune2fs 查询
[root@localhost test10g]# tune2fs -help
tune2fs 1.35 (28-Feb-2004)
tune2fs: invalid option -- h
Usage: tune2fs [-c max-mounts-count] [-e errors-behavior] [-g group]
        [-i interval[d|m|w]] [-j] [-J journal-options]
        [-l] [-s sparse-flag] [-m reserved-blocks-percent]
        [-o [^]mount-options[,...]] [-r reserved-blocks-count]
        [-u user] [-C mount-count] [-L volume-label] [-M last-mounted-dir]
        [-O [^]feature[,...]] [-T last-check-time] [-U UUID] device
[root@localhost test10g]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda2              8776068   7576504    753764 91% /
/dev/sda1               497829     16303    455824   4% /boot
none                    517300         0    517300   0% /dev/shm
/dev/sda5              1035660     96452    886600 10% /tmp
[root@localhost test10g]# tune2fs -l /dev/sda1|grep Block
Block count:              514048
Block size:               1024             
Blocks per group:         8192
[root@localhost test10g]# tune2fs -l /dev/sda2|grep Block
Block count:              2229018
Block size:               4096
Blocks per group:         32768
上面Block size即为块大小。

在WINDOWS系统上,可以用命令fsutil来查看,测试如下:
C:/Documents and Settings/ct2>fsutil --help
--help 是无效参数。
---- 支持的命令 ----

behavior        控制文件系统行为
dirty           管理卷的被损坏的位数
file            文件特定命令
fsinfo          文件系统信息
hardlink        硬链接管理
objectid        对象 ID 管理
quota           配额管理
reparsepoint    重分析点管理
sparse          稀疏文件控制
usn             USN 管理
volume          卷管理
C:/Documents and Settings/ct2>fsutil fsinfo ntfsinfo c:
NTFS 卷序列号 :       0x72ccb5f2ccb5b129
版本 :                         3.1
区数量 :                  0x0000000008ff8235
簇总数 :                  0x00000000011ff046
可用簇 :                  0x0000000000547b73
保留总数 :                  0x0000000000000050
每个扇区字节数 :               512
每个簇字节数 :               4096
每个 FileRecord 段的字节数    : 1024
每个 FileRecord 段的簇数 : 0
Mft 有效数据长度 :           0x0000000009cac000
Mft 起始 Lcn :                  0x00000000000c4df6
Mft2 起始 Lcn :                  0x00000000008ff823
Mft 区域起始 :                  0x0000000001067920
Mft 区域结尾   :                  0x000000000108ce60
上面簇字节数既为块大小。

linux文件系统

linux文件系统摘自《鸟哥的Linux私房菜》第八章

由此我們也能夠知道,每種作業系統能夠使用的檔案系統並不相同。 舉例來說,windows 98 以前的微軟作業系統主要利用的檔案系統是 FAT (或 FAT16),windows 2000 以後的版本有所謂的 NTFS 檔案系統,至於 Linux 的正統檔案系統則為 Ext2 (Linux second extended file system, ext2fs)這一個。此外,在預設的情況下,windows 作業系統是不會認識 Linux 的 Ext2 的。

傳統的磁碟與檔案系統之應用中,一個分割槽就是只能夠被格式化成為一個檔案系統,所以我們可以說一個 filesystem 就是一個 partition。但是由於新技術的利用,例如我們常聽到的LVM與軟體磁碟陣列(software raid), 這些技術可以將一個分割槽格式化為多個檔案系統(例如LVM),也能夠將多個分割槽合成一個檔案系統(LVM, RAID)! 所以說,目前我們在格式化時已經不再說成針對 partition 來格式化了, 通常我們可以稱呼一個可被掛載的資料為一個檔案系統而不是一個分割槽喔!

那麼檔案系統是如何運作的呢?這與作業系統的檔案資料有關。較新的作業系統的檔案資料除了檔案實際內容外, 通常含有非常多的屬性,例如 Linux 作業系統的檔案權限(rwx)與檔案屬性(擁有者、群組、時間參數等)。 檔案系統通常會將這兩部份的資料分別存放在不同的區塊,權限與屬性放置到 inode 中,至於實際資料則放置到 data block 區塊中。 另外,還有一個超級區塊 (superblock) 會記錄整個檔案系統的整體資訊,包括 inode 與 block 的總量、使用量、剩餘量等。

每個 inode 與 block 都有編號,至於這三個資料的意義可以簡略說明如下:

  • superblock:記錄此 filesystem 的整體資訊,包括inode/block的總量、使用量、剩餘量, 以及檔案系統的格式與相關資訊等;
  • inode:記錄檔案的屬性,一個檔案佔用一個inode,同時記錄此檔案的資料所在的 block 號碼;
  • block:實際記錄檔案的內容,若檔案太大時,會佔用多個 block 。

由於每個 inode 與 block 都有編號,而每個檔案都會佔用一個 inode ,inode 內則有檔案資料放置的 block 號碼。 因此,我們可以知道的是,如果能夠找到檔案的 inode 的話,那麼自然就會知道這個檔案所放置資料的 block 號碼, 當然也就能夠讀出該檔案的實際資料了。這是個比較有效率的作法,因為如此一來我們的磁碟就能夠在短時間內讀取出全部的資料, 讀寫的效能比較好囉。

我們將 inode 與 block 區塊用圖解來說明一下,如下圖所示,檔案系統先格式化出 inode 與 block 的區塊,假設某一個檔案的屬性與權限資料是放置到 inode 4 號(下圖較小方格內),而這個 inode 記錄了檔案資料的實際放置點為 2, 7, 13, 15 這四個 block 號碼,此時我們的作業系統就能夠據此來排列磁碟的讀取順序,可以一口氣將四個 block 內容讀出來! 那麼資料的讀取就如同下圖中的箭頭所指定的模樣了。

系统块大小(block size)
圖1.2.1、inode/block 資料存取示意圖

這種資料存取的方法我們稱為索引式檔案系統(indexed allocation)。那有沒有其他的慣用檔案系統可以比較一下啊? 有的,那就是我們慣用的隨身碟(快閃記憶體),隨身碟使用的檔案系統一般為 FAT 格式。FAT 這種格式的檔案系統並沒有 inode 存在,所以 FAT 沒有辦法將這個檔案的所有 block 在一開始就讀取出來。每個 block 號碼都記錄在前一個 block 當中, 他的讀取方式有點像底下這樣:

系统块大小(block size)
圖1.2.2、FAT檔案系統資料存取示意圖

上圖中我們假設檔案的資料依序寫入1->7->4->15號這四個 block 號碼中, 但這個檔案系統沒有辦法一口氣就知道四個 block 的號碼,他得要一個一個的將 block 讀出後,才會知道下一個 block 在何處。 如果同一個檔案資料寫入的 block 分散的太過厲害時,則我們的磁碟讀取頭將無法在磁碟轉一圈就讀到所有的資料, 因此磁碟就會多轉好幾圈才能完整的讀取到這個檔案的內容!

常常會聽到所謂的『磁碟重組』吧? 需要磁碟重組的原因就是檔案寫入的 block 太過於離散了,此時檔案讀取的效能將會變的很差所致。 這個時候可以透過磁碟重組將同一個檔案所屬的 blocks 彙整在一起,這樣資料的讀取會比較容易啊! 想當然爾,FAT 的檔案系統需要三不五時的磁碟重組一下,那麼 Ext2 是否需要磁碟重整呢?

由於 Ext2 是索引式檔案系統,基本上不太需要常常進行磁碟重組的。但是如果檔案系統使用太久, 常常刪除/編輯/新增檔案時,那麼還是可能會造成檔案資料太過於離散的問題,此時或許會需要進行重整一下的。 不過,老實說,鳥哥倒是沒有在 Linux 作業系統上面進行過 Ext2/Ext3 檔案系統的磁碟重組說!似乎不太需要啦!^_^


系统块大小(block size)Linux 的 EXT2 檔案系統(inode):

第六章當中我們介紹過 Linux 的檔案除了原有的資料內容外,還含有非常多的權限與屬性,這些權限與屬性是為了保護每個使用者所擁有資料的隱密性。 而前一小節我們知道 filesystem 裡面可能含有的 inode/block/superblock 等。為什麼要談這個呢?因為標準的 Linux 檔案系統 Ext2 就是使用這種 inode 為基礎的檔案系統啦!

而如同前一小節所說的,inode 的內容在記錄檔案的權限與相關屬性,至於 block 區塊則是在記錄檔案的實際內容。 而且檔案系統一開始就將 inode 與 block 規劃好了,除非重新格式化(或者利用 resize2fs 等指令變更檔案系統大小),否則 inode 與 block 固定後就不再變動。但是如果仔細考慮一下,如果我的檔案系統高達數百GB時, 那麼將所有的 inode 與 block 通通放置在一起將是很不智的決定,因為 inode 與 block 的數量太龐大,不容易管理。

為此之故,因此 Ext2 檔案系統在格式化的時候基本上是區分為多個區塊群組 (block group) 的,每個區塊群組都有獨立的 inode/block/superblock 系統。感覺上就好像我們在當兵時,一個營裡面有分成數個連,每個連有自己的聯絡系統, 但最終都向營部回報連上最正確的資訊一般!這樣分成一群群的比較好管理啦!整個來說,Ext2 格式化後有點像底下這樣:

系统块大小(block size)
圖1.3.1、ext2檔案系統示意圖(註1)

在整體的規劃當中,檔案系統最前面有一個開機磁區(boot sector),這個開機磁區可以安裝開機管理程式, 這是個非常重要的設計,因為如此一來我們就能夠將不同的開機管理程式安裝到個別的檔案系統最前端,而不用覆蓋整顆硬碟唯一的 MBR, 這樣也才能夠製作出多重開機的環境啊!至於每一個區塊群組(block group)的六個主要內容說明如後:


  • data block (資料區塊)

data block 是用來放置檔案內容資料地方,在 Ext2 檔案系統中所支援的 block 大小有 1K, 2K 及 4K 三種而已。在格式化時 block 的大小就固定了,且每個 block 都有編號,以方便 inode 的記錄啦。 不過要注意的是,由於 block 大小的差異,會導致該檔案系統能夠支援的最大磁碟容量與最大單一檔案容量並不相同。 因為 block 大小而產生的 Ext2 檔案系統限制如下:(註2)

Block 大小 1KB 2KB 4KB
最大單一檔案限制 16GB 256GB 2TB
最大檔案系統總容量 2TB 8TB 16TB

你需要注意的是,雖然 Ext2 已經能夠支援大於 2GB 以上的單一檔案容量,不過某些應用程式依然使用舊的限制, 也就是說,某些程式只能夠捉到小於 2GB 以下的檔案而已,這就跟檔案系統無關了! 舉例來說,鳥哥在環工方面的應用中有一套秀圖軟體稱為PAVE(註3), 這套軟體就無法捉到鳥哥在數值模式模擬後產生的大於 2GB 以上的檔案!害的鳥哥常常還要重跑數值模式...

除此之外 Ext2 檔案系統的 block 還有什麼限制呢?有的!基本限制如下:

  • 原則上,block 的大小與數量在格式化完就不能夠再改變了(除非重新格式化);
  • 每個 block 內最多只能夠放置一個檔案的資料;
  • 承上,如果檔案大於 block 的大小,則一個檔案會佔用多個 block 數量;
  • 承上,若檔案小於 block ,則該 block 的剩餘容量就不能夠再被使用了(磁碟空間會浪費)。

如上第四點所說,由於每個 block 僅能容納一個檔案的資料而已,因此如果你的檔案都非常小,但是你的 block 在格式化時卻選用最大的 4K 時,可能會產生一些容量的浪費喔!我們以底下的一個簡單例題來算一下空間的浪費吧!

例題:假設你的Ext2檔案系統使用 4K block ,而該檔案系統中有 10000 個小檔案,每個檔案大小均為 50bytes, 請問此時你的磁碟浪費多少容量?答:由於 Ext2 檔案系統中一個 block 僅能容納一個檔案,因此每個 block 會浪費『 4096 - 50 = 4046 (byte)』, 系統中總共有一萬個小檔案,所有檔案容量為:50 (bytes) x 10000 = 488.3Kbytes,但此時浪費的容量為:『 4046 (bytes) x 10000 = 38.6MBytes 』。想一想,不到 1MB 的總檔案容量卻浪費將近 40MB 的容量,且檔案越多將造成越多的磁碟容量浪費。

什麼情況會產生上述的狀況呢?例如 BBS 網站的資料啦!如果 BBS 上面的資料使用的是純文字檔案來記載每篇留言, 而留言內容如果都寫上『如題』時,想一想,是否就會產生很多小檔案了呢?

好,既然大的 block 可能會產生較嚴重的磁碟容量浪費,那麼我們是否就將 block 大小訂為 1K 即可? 這也不妥,因為如果 block 較小的話,那麼大型檔案將會佔用數量更多的 block ,而 inode 也要記錄更多的 block 號碼,此時將可能導致檔案系統不良的讀寫效能。

所以我們可以說,在您進行檔案系統的格式化之前,請先想好該檔案系統預計使用的情況。 以鳥哥來說,我的數值模式模擬平台隨便一個檔案都好幾百 MB,那麼 block 容量當然選擇較大的!至少檔案系統就不必記錄太多的 block 號碼,讀寫起來也比較方便啊!


  • inode table (inode 表格)

再來討論一下 inode 這個玩意兒吧!如前所述 inode 的內容在記錄檔案的屬性以及該檔案實際資料是放置在哪幾號 block 內! 基本上,inode 記錄的檔案資料至少有底下這些:(註4)

  • 該檔案的存取模式(read/write/excute);
  • 該檔案的擁有者與群組(owner/group);
  • 該檔案的容量;
  • 該檔案建立或狀態改變的時間(ctime);
  • 最近一次的讀取時間(atime);
  • 最近修改的時間(mtime);
  • 定義檔案特性的旗標(flag),如 SetUID...;
  • 該檔案真正內容的指向 (pointer);

inode 的數量與大小也是在格式化時就已經固定了,除此之外 inode 還有些什麼特色呢?

  • 每個 inode 大小均固定為 128 bytes;
  • 每個檔案都僅會佔用一個 inode 而已;
  • 承上,因此檔案系統能夠建立的檔案數量與 inode 的數量有關;
  • 系統讀取檔案時需要先找到 inode,並分析 inode 所記錄的權限與使用者是否符合,若符合才能夠開始實際讀取 block 的內容。

我們約略來分析一下 inode / block 與檔案大小的關係好了。inode 要記錄的資料非常多,但偏偏又只有 128bytes 而已, 而 inode 記錄一個 block 號碼要花掉 4byte ,假設我一個檔案有 400MB 且每個 block 為 4K 時, 那麼至少也要十萬筆 block 號碼的記錄呢!inode 哪有這麼多可記錄的資訊?為此我們的系統很聰明的將 inode 記錄 block 號碼的區域定義為12個直接,一個間接, 一個雙間接與一個三間接記錄區。這是啥?我們將 inode 的結構畫一下好了。

系统块大小(block size)
圖1.3.2、inode 結構示意圖(註5)

上圖最左邊為 inode 本身 (128 bytes),裡面有 12 個直接指向 block 號碼的對照,這 12 筆記錄就能夠直接取得 block 號碼啦! 至於所謂的間接就是再拿一個 block 來當作記錄 block 號碼的記錄區,如果檔案太大時, 就會使用間接的 block 來記錄號碼。如上圖 1.3.2 當中間接只是拿一個 block 來記錄額外的號碼而已。 同理,如果檔案持續長大,那麼就會利用所謂的雙間接,第一個 block 僅再指出下一個記錄號碼的 block 在哪裡, 實際記錄的在第二個 block 當中。依此類推,三間接就是利用第三層 block 來記錄號碼啦!

這樣子 inode 能夠指定多少個 block 呢?我們以較小的 1K block 來說明好了,可以指定的情況如下:

  • 12 個直接指向: 12*1K=12K
    由於是直接指向,所以總共可記錄 12 筆記錄,因此總額大小為如上所示;

  • 間接: 256*1K=256K
    每筆 block 號碼的記錄會花去 4bytes,因此 1K 的大小能夠記錄 256 筆記錄,因此一個間接可以記錄的檔案大小如上; 

  • 雙間接: 256*256*1K=2562K
    第一層 block 會指定 256 個第二層,每個第二層可以指定 256 個號碼,因此總額大小如上;

  • 三間接: 256*256*256*1K=2563K
    第一層 block 會指定 256 個第二層,每個第二層可以指定 256 個第三層,每個第三層可以指定 256 個號碼,因此總額大小如上;

  • 總額:將直接、間接、雙間接、三間接加總,得到 12 + 256 + 256*256 + 256*256*256 (K) = 16GB

此時我們知道當檔案系統將 block 格式化為 1K 大小時,能夠容納的最大檔案為 16GB,比較一下檔案系統限制表的結果可發現是一致的!但這個方法不能用在 2K 及 4K block 大小的計算中, 因為大於 2K 的 block 將會受到 Ext2 檔案系統本身的限制,所以計算的結果會不太符合之故。


  • Superblock (超級區塊)

Superblock 是記錄整個 filesystem 相關資訊的地方, 沒有 Superblock ,就沒有這個 filesystem 了。他記錄的資訊主要有:

  • block 與 inode 的總量;
  • 未使用與已使用的 inode / block 數量;
  • block 與 inode 的大小 (block 為 1, 2, 4K,inode 為 128 bytes);
  • filesystem 的掛載時間、最近一次寫入資料的時間、最近一次檢驗磁碟 (fsck) 的時間等檔案系統的相關資訊;
  • 一個 valid bit 數值,若此檔案系統已被掛載,則 valid bit 為 0 ,若未被掛載,則 valid bit 為 1 。

Superblock 是非常重要的,因為我們這個檔案系統的基本資訊都寫在這裡,因此,如果 superblock 死掉了, 你的檔案系統可能就需要花費很多時間去挽救啦!一般來說, superblock 的大小為 1024bytes。相關的 superblock 訊息我們等一下會以 dumpe2fs 指令來呼叫出來觀察喔!

此外,每個 block group 都可能含有 superblock 喔!但是我們也說一個檔案系統應該僅有一個 superblock 而已,那是怎麼回事啊? 事實上除了第一個 block group 內會含有 superblock 之外,後續的 block group 不一定含有 superblock , 而若含有 superblock 則該 superblock 主要是做為第一個 block group 內 superblock 的備份咯,這樣可以進行 superblock 的救援呢!


  • Filesystem Description (檔案系統描述說明)

這個區段可以描述每個 block group 的開始與結束的 block 號碼,以及說明每個區段 (superblock, bitmap, inodemap, data block) 分別介於哪一個 block 號碼之間。這部份也能夠用 dumpe2fs 來觀察的。


  • block bitmap (區塊對照表)

如果你想要新增檔案時總會用到 block 吧!那你要使用哪個 block 來記錄呢?當然是選擇『空的 block 』來記錄新檔案的資料囉。 那你怎麼知道哪個 block 是空的?這就得要透過 block bitmap 的輔助了。從 block bitmap 當中可以知道哪些 block 是空的,因此我們的系統就能夠很快速的找到可使用的空間來處置檔案囉。

同樣的,如果你刪除某些檔案時,那麼那些檔案原本佔用的 block 號碼就得要釋放出來, 此時在 block bitmap 當中相對應到該 block 號碼的標誌就得要修改成為『未使用中』囉!這就是 bitmap 的功能。


  • inode bitmap (inode 對照表)

這個其實與 block bitmap 是類似的功能,只是 block bitmap 記錄的是使用與未使用的 block 號碼, 至於 inode bitmap 則是記錄使用與未使用的 inode 號碼囉!


瞭解了檔案系統的概念之後,再來當然是觀察這個檔案系統囉!剛剛談到的各部分資料都與 block 號碼有關! 每個區段與 superblock 的資訊都可以使用 dumpe2fs 這個指令來查詢的!查詢的方法與實際的觀察如下:

[root@www ~]# dumpe2fs [-bh] 裝置檔名
選項與參數:
-b :列出保留為壞軌的部分(一般用不到吧!?)
-h :僅列出 superblock 的資料,不會列出其他的區段內容!


範例:找出我的根目錄磁碟檔名,並觀察檔案系統的相關資訊
[root@www ~]# df <==這個指令可以叫出目前掛載的裝置
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hdc2 9920624 3822848 5585708 41% / <==就是這個光!
/dev/hdc3 4956316 141376 4559108 4% /home
/dev/hdc1 101086 11126 84741 12% /boot
tmpfs 371332 0 371332 0% /dev/shm

[root@www ~]# dumpe2fs /dev/hdc2
dumpe2fs 1.39 (29-May-2006)
Filesystem volume name: /1 <==這個是檔案系統的名稱(Label)
Filesystem features: has_journal ext_attr resize_inode dir_index
filetype needs_recovery sparse_super large_file
Default mount options: user_xattr acl <==預設掛載的參數
Filesystem state: clean <==這個檔案系統是沒問題的(clean)
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 2560864 <==inode的總數
Block count: 2560359 <==block的總數
Free blocks: 1524760 <==還有多少個 block 可用
Free inodes: 2411225 <==還有多少個 inode 可用
First block: 0
Block size: 4096 <==每個 block 的大小啦!
Filesystem created: Fri Sep 5 01:49:20 2008
Last mount time: Mon Sep 22 12:09:30 2008
Last write time: Mon Sep 22 12:09:30 2008
Last checked: Fri Sep 5 01:49:20 2008
First inode: 11
Inode size: 128 <==每個 inode 的大小
Journal inode: 8 <==底下這三個與下一小節有關
Journal backup: inode blocks
Journal size: 128M

Group 0: (Blocks 0-32767) <==第一個 data group 內容, 包含 block 的啟始/結束號碼
Primary superblock at 0, Group descriptors at 1-1 <==超級區塊在 0 號 block
Reserved GDT blocks at 2-626
Block bitmap at 627 (+627), Inode bitmap at 628 (+628)
Inode table at 629-1641 (+629) <==inode table 所在的 block
0 free blocks, 32405 free inodes, 2 directories <==所有 block 都用完了!
Free blocks:
Free inodes: 12-32416 <==剩餘未使用的 inode 號碼
Group 1: (Blocks 32768-65535)
....(底下省略)....
# 由於資料量非常的龐大,因此鳥哥將一些資訊省略輸出了!上表與你的螢幕會有點差異。
# 前半部在秀出 supberblock 的內容,包括標頭名稱(Label)以及inode/block的相關資訊
# 後面則是每個 block group 的個別資訊了!您可以看到各區段資料所在的號碼!
# 也就是說,基本上所有的資料還是與 block 的號碼有關就是了!很重要!

如上所示,利用 dumpe2fs 可以查詢到非常多的資訊,不過依內容主要可以區分為上半部是 superblock 內容, 下半部則是每個 block group 的資訊了。從上面的表格中我們可以觀察到這個 /dev/hdc2 規劃的 block 為 4K, 第一個 block 號碼為 0 號,且 block group 內的所有資訊都以 block 的號碼來表示的。 然後在 superblock 中還有談到目前這個檔案系統的可用 block 與 inode 數量喔!

至於 block group 的內容我們單純看 Group0 資訊好了。從上表中我們可以發現:

  • Group0 所佔用的 block 號碼由 0 到 32767 號,superblock 則在第 0 號的 block 區塊內!
  • 檔案系統描述說明在第 1 號 block 中;
  • block bitmap 與 inode bitmap 則在 627 及 628 的 block 號碼上。
  • 至於 inode table 分佈於 629-1641 的 block 號碼中!
  • 由於 (1)一個 inode 佔用 128 bytes ,(2)總共有 1641 - 629 + 1(629本身) = 1013 個 block 花在 inode table 上, (3)每個 block 的大小為 4096 bytes(4K)。由這些數據可以算出 inode 的數量共有 1013 * 4096 / 128 = 32416 個 inode 啦!
  • 這個 Group0 目前沒有可用的 block 了,但是有剩餘 32405 個 inode 未被使用;
  • 剩餘的 inode 號碼為 12 號到 32416 號。

如果你對檔案系統的詳細資訊還有更多想要瞭解的話,那麼請參考本章最後一小節的介紹喔! 否則檔案系統看到這裡對於基礎認知您應該是已經相當足夠啦!底下則是要探討一下, 那麼這個檔案系統概念與實際的目錄樹應用有啥關連啊?


系统块大小(block size)與目錄樹的關係

由前一小節的介紹我們知道在 Linux 系統下,每個檔案(不管是一般檔案還是目錄檔案)都會佔用一個 inode , 且可依據檔案內容的大小來分配多個 block 給該檔案使用。而由第六章的權限說明中我們知道目錄的內容在記錄檔名, 一般檔案才是實際記錄資料內容的地方。那麼目錄與檔案在 Ext2 檔案系統當中是如何記錄資料的呢? 基本上可以這樣說:


  • 目錄

當我們在 Linux 下的 ext2 檔案系統建立一個目錄時, ext2 會分配一個 inode 與至少一塊 block 給該目錄。其中,inode 記錄該目錄的相關權限與屬性,並可記錄分配到的那塊 block 號碼; 而 block 則是記錄在這個目錄下的檔名與該檔名佔用的 inode 號碼資料。也就是說目錄所佔用的 block 內容在記錄如下的資訊:

系统块大小(block size)
圖1.4.1、目錄佔用的 block 記錄的資料示意圖

如果想要實際觀察 root 家目錄內的檔案所佔用的 inode 號碼時,可以使用 ls -i 這個選項來處理:

[root@www ~]# ls -li
total 92
654683 -rw------- 1 root root 1474 Sep 4 18:27 anaconda-ks.cfg
648322 -rw-r--r-- 1 root root 42304 Sep 4 18:26 install.log
648323 -rw-r--r-- 1 root root 5661 Sep 4 18:25 install.log.syslog

由於每個人所使用的電腦並不相同,系統安裝時選擇的項目與 partition 都不一樣,因此你的環境不可能與我的 inode 號碼一模一樣!上表的左邊所列出的 inode 僅是鳥哥的系統所顯示的結果而已!而由這個目錄的 block 結果我們現在就能夠知道, 當你使用『 ll / 』時,出現的目錄幾乎都是 1024 的倍數,為什麼呢?因為每個 block 的數量都是 1K, 2K, 4K 嘛! 看一下鳥哥的環境:

[root@www ~]# ll -d / /bin /boot /proc /lost+found /sbin
drwxr-xr-x 23 root root 4096 Sep 22 12:09 / <==一個 4K block
drwxr-xr-x 2 root root 4096 Sep 24 00:07 /bin <==一個 4K block
drwxr-xr-x 4 root root 1024 Sep 4 18:06 /boot <==一個 1K block
drwx------ 2 root root 16384 Sep 5 01:49 /lost+found <==四個 4K block
dr-xr-xr-x 96 root root 0 Sep 22 20:07 /proc <==此目錄不佔硬碟空間
drwxr-xr-x 2 root root 12288 Sep 5 12:33 /sbin <==三個 4K block

由於鳥哥的根目錄 /dev/hdc2 使用的 block 大小為 4K ,因此每個目錄幾乎都是 4K 的倍數。 其中由於 /sbin 的內容比較複雜因此佔用了 3 個 block ,此外,鳥哥的系統中 /boot 為獨立的 partition , 該 partition 的 block 為 1K 而已,因此該目錄就僅佔用 1024 bytes 的大小囉!至於奇怪的 /proc 我們在第六章就講過該目錄不佔硬碟容量, 所以當然耗用的 block 就是 0 囉!

Tips:
由上面的結果我們知道目錄並不只會佔用一個 block 而已,也就是說: 在目錄底下的檔案數如果太多而導致一個 block 無法容納的下所有的檔名與 inode 對照表時,Linux 會給予該目錄多一個 block 來繼續記錄相關的資料;
系统块大小(block size)

  • 檔案:

當我們在 Linux 下的 ext2 建立一個一般檔案時, ext2 會分配一個 inode 與相對於該檔案大小的 block 數量給該檔案。例如:假設我的一個 block 為 4 Kbytes ,而我要建立一個 100 KBytes 的檔案,那麼 linux 將分配一個 inode 與 25 個 block 來儲存該檔案! 但同時請注意,由於 inode 僅有 12 個直接指向,因此還要多一個 block 來作為區塊號碼的記錄喔!


  • 目錄樹讀取:

好了,經過上面的說明你也應該要很清楚的知道 inode 本身並不記錄檔名,檔名的記錄是在目錄的 block 當中。 因此在第六章檔案與目錄的權限說明中, 我們才會提到『新增/刪除/更名檔名與目錄的 w 權限有關』的特色!那麼因為檔名是記錄在目錄的 block 當中, 因此當我們要讀取某個檔案時,就務必會經過目錄的 inode 與 block ,然後才能夠找到那個待讀取檔案的 inode 號碼, 最終才會讀到正確的檔案的 block 內的資料。

由於目錄樹是由根目錄開始讀起,因此系統透過掛載的資訊可以找到掛載點的 inode 號碼(通常一個 filesystem 的最頂層 inode 號碼會由 2 號開始喔!),此時就能夠得到根目錄的 inode 內容,並依據該 inode 讀取根目錄的 block 內的檔名資料,再一層一層的往下讀到正確的檔名。

舉例來說,如果我想要讀取 /etc/passwd 這個檔案時,系統是如何讀取的呢?

[root@www ~]# ll -di / /etc /etc/passwd
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /
1912545 drwxr-xr-x 105 root root 12288 Oct 14 04:02 /etc
1914888 -rw-r--r-- 1 root root 1945 Sep 29 02:21 /etc/passwd

在鳥哥的系統上面與 /etc/passwd 有關的目錄與檔案資料如上表所示,該檔案的讀取流程為(假設讀取者身份為 vbird 這個一般身份使用者):

  1. / 的 inode:
    透過掛載點的資訊找到 /dev/hdc2 的 inode 號碼為 2 的根目錄 inode,且 inode 規範的權限讓我們可以讀取該 block 的內容(有 r 與 x) ;

  2. / 的 block:
    經過上個步驟取得 block 的號碼,並找到該內容有 etc/ 目錄的 inode 號碼 (1912545); 

  3. etc/ 的 inode:
    讀取 1912545 號 inode 得知 vbird 具有 r 與 x 的權限,因此可以讀取 etc/ 的 block 內容; 

  4. etc/ 的 block:
    經過上個步驟取得 block 號碼,並找到該內容有 passwd 檔案的 inode 號碼 (1914888); 

  5. passwd 的 inode:
    讀取 1914888 號 inode 得知 vbird 具有 r 的權限,因此可以讀取 passwd 的 block 內容; 

  6. passwd 的 block:
    最後將該 block 內容的資料讀出來。