1. 硬盤物理結構
硬盤物理上主要分為:
- 盤片
- 磁道
- 扇區
- 機械臂
- 磁頭
- 主軸
磁道:
當硬盤盤片旋轉時,磁頭若固定在一個位置上,則磁頭會在盤片表面划出一個圓形軌跡,這些圓形軌跡就叫做磁道。以盤片中心為圓心,由此可以划分出很多磁道來, 這些磁道用肉眼是根本看不到的,因為它們僅 是盤面上以特殊方式磁化了的一些磁化區,硬盤上的信息便是沿着這樣的軌道存放的,盤片上的磁道由外向內依次從“0”開始進行編號。
柱面:
由於硬盤可以由很多盤片組成,不同盤片的相同磁道就組成了柱面(cylinder),如第一個圖片。
磁頭:
假設有N個盤片組成的硬盤,那么有2N個盤面(一個盤片有2面),那么磁頭也就有2N個,即每個盤面有一個磁頭。
扇區:
早期的硬盤盤片的盤面以圓心開始向外放射狀將磁道分割成等分的弧段,這些弧段便是硬盤的扇區。每個扇區一般規定大小為512byte,這里大家應該比較疑惑,外圈周長很明顯比內圈要長,怎么可能每個扇區都是512byte?其實答案早期硬盤外圈存儲比內圈存儲密度低一些,所以外圈很長但是仍然只能存儲512byte,因此如果我們知道了柱面數(磁道數) Cylinders、磁頭數Heads、扇區數Sectors,基本上硬盤的容量我們能夠計算出來 硬盤總容量= Cylinders * Heads * Sectors * 512byte。但是由於早期硬盤外圈密度低,導致盤片利用率不高,現在的硬盤盤片則采用內外存儲密度一致的方式,每個磁道都划分成以512byte大小的弧段,這樣也造成了內外磁道上扇區數量會不一樣,外圈上的扇區數要多於內圈扇區數。
磁盤尋址方式:
硬盤存取、讀取數據,首先要做的就是尋址,即定位到數據所在的物理地址,在硬盤上就要找到對應的柱面、磁頭以及對應的扇區,那么怎么尋址呢? 有兩種方式:CHS和LBA
2. 磁盤分區
一般使用硬盤,首先會對硬盤進行分區,然后對分區使用某個文件系統格式(NTFS、FAT、ext2/ext3/ext4)進行分區格式化,然后才能正常使用。
柱面是分區的最小單元,即分區是某個柱面號開始到某個柱面號結束的。
如圖,柱面1~200可以分為一個區,柱面201~500再划分為一個區,501~1000再划分為一個區,以此類推。柱面0沒有在任何分區里面,為何?
前面說到硬盤從外圈(柱面0)到內圈扇區是依次編號,看似各個扇區沒有什么區別,但是這里硬盤的柱面0的第一個扇區(邏輯扇區0,CHS表示應該是0/0/1)卻是最重要的,因為硬盤的第一個扇區記錄了整個硬盤的重要信息,第一個扇區(512個字節)主要記錄了兩部分:
(1)MBR(Master Boot Record):主引導程序就放在這里,主引導程序是引導操作系統的一個程序,但是這部分只占 446 字節
(2)DPT(Disk Partition table):硬盤分區表也在這里,分區表就是用來記錄硬盤的分區情況的,例如c盤是1~200柱面,d盤是201~500柱面,分區表總共只占64字節,可以看出,分區其實很簡單,就是在這個表里面修改一下記錄就重新分區了,但是由於只有64字節,而一條記錄就要占用16字節,這個分區表最多只能記錄4個分區信息,為了繼續分出更多分區來,引入了擴展分區的概念,也就是說,在這4個分區中,可以使用其中一條記錄來記錄擴展分區的信息,然后在擴展分區中再繼續划分邏輯分區,而邏輯分區的分區記錄則記錄在擴展分區的第一個扇區中,如此則可以像鏈表一樣划分出很多分區來。但是請注意,一個分區表中可以有1~4條主分區,但是最多只能有1個擴展分區。
舉例,主分區可以是P1:1~200,擴展分區P2: 201~1400,擴展分區開始的第一個扇區可以用來記錄擴展分區中划分出來的邏輯分區。
3. 理解 Linux 的 inode / block / superblock
磁盤分區完畢后還需要進行格式化(format),之后操作系統才能夠使用這個文件系統。 為什么需要進行『格式化』呢?
這是因為每種操作系統所設定的文件屬性/權限並不相同, 為了存放這些文件所需的數據,因此就需要將分區進行格式化,以成為操作系統能夠利用的『文件系統格式(filesystem)』。每種操作系統能夠使用的文件系統並不相同。
傳統的磁盤與文件系統應用中,一個分區就是只能夠被格式化成為一個文件系統,所以可以說一個 filesystem 就是一個 partition。但是由於新技術的利用,例如常聽到的 LVM 與軟件磁盤陣列(software raid), 這些技術可以將一個分區格式化為多個文件系統(例如 LVM),也能夠將多個分區合成一個文件系統(LVM, RAID)! 所以說,目前在格式化時已經不再說成針對partition來格式化了, 通常稱呼一個可被掛載的數據為一個文件系統而不是一個分區。
文件系統通常會將這兩部份的數據分別存放在不同的區塊,權限與屬性放置到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 內容讀出來。這種數據存取的方法稱為索引式文件系統(indexed allocation)
那有沒有其他的慣用文件系統可以比較一下啊? 有的,那就是我們慣用的隨身碟(閃存),隨身碟使用的文件系統一般為 FAT 格式。FAT 這種格式的文件系統並沒有 inode 存在,所以 FAT 沒有辦法將這個文件的所有 block 在一開始就讀取出來。每個 block 號碼都記錄在前一個 block 當中, 他的讀取方式有點像底下這樣:
上圖中我們假設文件的數據依序寫入 1->7->4->15 號這四個 block 號碼中, 但這個文件系統沒有辦法一口氣就知道四個 block 的號碼,他得要一個一個的將 block 讀出后,才會知道下一個 block 在何處。 如果同一個文件數據寫入的 block 分散的太過厲害時,則我們的磁盤讀取頭將無法在磁盤轉一圈就讀到所有的數據, 因此磁盤就會多轉好幾圈才能完整的讀取到這個文件的內容!
常常會聽到所謂的『碎片整理』吧?需要碎片整理的原因就是文件寫入的 block 太過於離散了,此時文件讀取的效能將會變的很差所致。 這個時候可以透過碎片整理將同一個文件所屬的 blocks 匯整在一起,這樣數據的讀取會比較容易啊! 想當然爾,FAT 的文件系統需要經常的碎片整理一下,那么 Ext2 是否需要磁盤重整呢?
由於 Ext2 是索引式文件系統,基本上不太需要常常進行碎片整理的。但是如果文件系統使用太久,常常刪除/編輯/新增文件時,那么還是可能會造成文件數據太過於離散的問題,此時或許會需要進行重整一下的。
inode 的內容在記錄文件的權限與相關屬性,至於 block 區塊則是在記錄文件的實際內容。 而且文件系統一開始就將 inode 與 block 規划好了,除非重新格式化(或者利用 resize2fs 等指令變更文件系統大小),否則 inode 與 block 固定后就不再變動。但是如果仔細考慮一下,如果我的文件系統高達數百 GB 時, 那么將所有的 inode 與 block 通通放置在一起將是很不智的決定,因為 inode 與 block 的數量太龐大,不容易管理。因此 文件系統在格式化的時候基本上是區分為多個區塊群組(block group)的,每個區塊群組都有獨立的 inode / block / superblock 系統。
感覺上就好像我們在當兵時,一個營里面有分成數個連,每個連有自己的聯絡系統, 但最終都向營部回報連上最正確的信息一般!這樣分成一群群的比較好管理啦!整個來說,文件系統格式化后有點像底下這樣:
在整體的規划中,文件系統最前面有一個啟動扇區(boot sector),這個啟動扇區可以安裝開機管理程序,這是個非常重要的設計,因為如此一來我們就能夠將不同的開機管理程序安裝到個別的文件系統最前端,而不用覆蓋整顆磁盤唯一的 MBR, 這樣也才能夠制作出多重引導的環境。
每一個區塊群組(block group)的六個主要內容說明:
data block (資源區塊)
data block 是用來放置文件內容數據的地方,在文件系統中所支持的block 大小有 1k, 2k, 4k 三種而已。在格式化時 block 的大小是固定了,且每個 block 都是有編號,以方便 inode 的記錄不過要注意的是,由於 block 大小的差異,會導致該文件系統能夠支持的最大磁盤容量與最大單一文件容量並不相同。 因為 block 大小而產生的 文件系統限制如下:
block 基本限制如下:
- block 的大小與數量在格式化完就不能再改變了;
- 每個 block 內最多只能夠放置一個文件的數據;
- 如果文件大於 block 的大小,則一個文件會占用多個 block 數量;
- 若文件小於 block,則該 block 的剩余容量就不能夠再被使用了(磁盤空間會浪費)
如上第四點所說,由於每個 block 僅能容納一個文件的數據而已,因此如果你的文件都非常小,但是你的 block 在格式化時卻選用最大的 4K 時,可能會產生一些容量的浪費喔!我們以底下的一個
簡單例題來算一下空間的浪費吧!
什么情況會產生上述的狀況呢?
例如 BBS 網站的數據啦!如果 BBS 上面的數據使用的是純文本文件來記載每篇留言, 而留言內容如果都寫上『如題』時,想一想,是否就會產生很多小文件了呢?
好,既然大的 block 可能會產生較嚴重的磁盤容量浪費,那么我們是否就將 block 大小訂為 1K 即可? 這也不妥,因為如果 block 較小的話,那么大型文件將會占用數量更多的 block ,而 inode 也要記錄更多的 block 號碼,此時將可能導致文件系統不良的讀寫效能。
inode 是什么
文件存儲在硬盤上,硬盤的最小存儲單位叫做 “扇區(Sector)”。每個扇區儲存 512 字節(相當於 0.5KB)
操作系統讀取硬盤的時候,不會一個個扇區的讀取,這樣效率太低,而是一次性連續讀取多個扇區,即一次性讀取一個"塊"(block)。這種由多個扇區組成的"塊",是文件存取的最小單位。"塊"的大小,最常見的是4KB,即連續八個 sector組成一個 block。
文件數據都儲存在"塊"中,那么很顯然,還必須找到一個地方儲存文件的元信息,比如文件的創建者、文件的創建日期、文件的大小等等。這種儲存文件元信息的區域就叫做inode,中文譯名為"索引節點"。
每一個文件都有對應的inode,里面包含了與該文件有關的一些信息。
inode 的內容
inode包含文件的元信息,具體來說有以下內容:
- 文件的字節數
- 文件擁有者的User ID
- 文件的Group ID
- 文件的讀、寫、執行權限
- 文件的時間戳,共有三個:ctime指inode上一次變動的時間,mtime指文件內容上一次變動的時間,atime指文件上一次打開的時間。
- 鏈接數,即有多少文件名指向這個inode
- 文件數據block的位置
可以用stat命令,查看某個文件的inode信息:
總之,除了文件名以外的所有文件信息,都存在inode之中。至於為什么沒有文件名,下文會有詳細解釋。
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命令。
查看每個inode節點的大小,可以用如下命令:
注意:
dumpe2fs 僅支持在 ext2/3/4 文件系統
如果是 xfs 需要使用 xfs_info 查看
inode 號碼
每個inode都有一個號碼,操作系統用inode號碼來識別不同的文件。
這里值得重復一遍,Unix/linux系統內部不使用文件名,而使用inode號碼來識別文件。對於系統來說,文件名只是inode號碼便於識別的別稱或者綽號。
表面上,用戶通過文件名,打開文件。實際上,系統內部這個過程分成三步:
- 系統找到這個文件名對應的inode號碼;
- 通過inode號碼,獲取inode信息;
- 根據inode信息,找到文件數據所在的block,讀出數據
使用ls -i命令,可以看到文件名對應的inode號碼:
目錄文件
Unix/Linux系統中,目錄(directory)也是一種文件。打開目錄,實際上就是打開目錄文件。
目錄文件的結構非常簡單,就是一系列目錄項(dirent)的列表。每個目錄項,由兩部分組成:所包含文件的文件名,以及該文件名對應的inode號碼。
ls命令只列出目錄文件中的所有文件名
ls -i命令列出整個目錄文件,即文件名和inode號碼:
如果要查看文件的詳細信息,就必須根據inode號碼,訪問inode節點,讀取信息。ls -l命令列出文件的詳細信息。
理解了上面這些知識,就能理解目錄的權限。目錄文件的讀權限(r)和寫權限(w),都是針對目錄文件本身(即不同用戶能以什么權限訪問操作對該目錄文件,例如這里不同用戶對tmp目錄文件(d可以查出tmp是目錄文件,d表示directory,即目錄)分別為rwxr-xr-x,第一組的三個字符,即rwx,表示文件擁有者用戶的對該文件的讀寫權限,第二組的三個字符,即r-x,表示文件擁有者用戶所在的用戶組里的其他用戶對該文件的讀寫權限,第三組的三個字符,即r-x,表示文件擁有者用戶所在的用戶組以外的用戶對該文件的讀寫權限。一個某個用戶下運行的進程訪問操作該目錄文件只能以該用戶所具有的對該目錄文件的權限進行操作)。由於目錄文件內只有文件名和inode號碼,所以如果只有讀權限,只能獲取文件名,無法獲取其他信息,因為其他信息都儲存在inode節點中,而讀取inode節點內的信息需要目錄文件的執行權限(x)。
硬鏈接
一般情況下,文件名和inode號碼是"一一對應"關系,每個inode號碼對應一個文件名。但是,Unix/Linux系統允許,多個文件名指向同一個inode號碼。
這意味着,可以用不同的文件名訪問同樣的內容;對文件內容進行修改,會影響到所有文件名;但是,刪除一個文件名,不影響另一個文件名的訪問。這種情況就被稱為"硬鏈接"(hard link)。
ln 命令可以創建硬鏈接:
ln 源文件 目標文件
運行上面這條命令以后,源文件與目標文件的inode號碼相同,都指向同一個inode。inode信息中有一項叫做"鏈接數",記錄指向該inode的文件名總數,這時就會增加1。
反過來,刪除一個文件名,就會使得inode節點中的"鏈接數"減1。當這個值減到0,表明沒有文件名指向這個inode,系統就會回收這個inode號碼,以及其所對應block區域。
軟鏈接
除了硬鏈接以外,還有一種特殊情況。
文件A 和 文件B 的 inode 號碼雖然不一樣,但是文件A 的內容是文件B 的路徑。讀取文件A時,系統會自動將訪問者導向文件B。因此,無論打開哪一個文件,最終讀取的都是文件B。這時,文件A就稱為文件B的"軟鏈接"(soft link)或者"符號鏈接(symbolic link)。
這意味着,文件A依賴於文件B而存在,如果刪除了文件B,打開文件A就會報錯:"No such file or directory"。這是軟鏈接與硬鏈接最大的不同:文件A指向文件B的文件名,而不是文件B的inode號碼,文件B的inode"鏈接數"不會因此發生變化。
inode 的特殊作用
由於inode號碼與文件名分離,這種機制導致了一些Unix/Linux系統特有的現象。
(1)有時,文件名包含特殊字符,無法正常刪除。這時,直接刪除inode節點,就能起到刪除文件的作用。
(2)移動文件或重命名文件,只是改變文件名,不影響inode號碼。
(3)打開一個文件以后,系統就以inode號碼來識別這個文件,不再考慮文件名。因此,通常來說,系統無法從inode號碼得知文件名。
第3點使得軟件更新變得簡單,可以在不關閉軟件的情況下進行更新,不需要重啟。因為系統通過inode號碼,識別運行中的文件,不通過文件名。更新的時候,新版文件以同樣的文件名,生成一個新的inode,不會影響到運行中的文件。等到下一次運行這個軟件的時候,文件名就自動指向新版文件,舊版文件的inode則被回收。
總結:
- 一個 inode 對應一個文件,而一個文件根據其大小,會占用多塊 blocks;
- 更為准確的來說,一個文件只對應一個Inode。因為硬鏈接其實不是創建新文件,只是在Directory中寫入了新的對應關系而已;
- 當刪除文件時,只是把 inode 標記為可用,文件在block 中的內容是沒有被清除的,只有在有新的文件需要占用block的時候,才會被覆蓋。
文章參考自網絡 和 《鳥哥私房菜》
參考鏈接:
https://www.cnblogs.com/doll-net/p/6090298.html
https://blog.csdn.net/Ohmyberry/article/details/80427492