Linux學習筆記之文件讀取過程


0x00 概述

對於Linux系統來說,一切的數據都起源於磁盤中存儲的文件。Linux文件系統的結構及其在磁盤中是如何存儲的?操作系統是怎樣找到這些文件進行讀取的?這一章主要圍繞這幾個問題進行介紹(以Ext2文件系統(傳統的linux文件系統)為例)。

 

0x01 Linux系統目錄樹

linux文件系統所有文件和目錄都是由目錄開始的,以樹的形式展開,如下圖所示:

根據FHS的基本定義,根目錄下面的各個目錄(如usr,var)基本上都有其特定的意義,在此不多做介紹。重點說一下根目錄'/'的作用和意義:

  • 其他所有目錄都是由根目錄衍生出來的。
  • 根目錄中包含了開機軟件、系統內核文件、函數庫、文件系統修復程序等。

因此,根目錄(/)所在的分區應該越小越好,應用程序所安裝的軟件最好不要與根目錄存放在同一個分區。根目錄越小,系統性能會更好,根目錄所在的文件系統也較不容易出現問題。

 

0x02 文件(目錄)存儲方式

linux中,磁盤(硬盤)上的存儲划分如下圖所示:

  • MBR: 主引導分區。
  • 自舉塊(引導分區Boot Sector):分區中文件系統自身引導程序存放的地方。
  • 超級塊(Super block): 記錄整個文件系統相關的信息的地方,它記錄的信息主要有:block與inode的總量、使用量、剩余量,文件系統的掛載時間,最近一次寫入數據的時間等。
  • 柱面組(塊組) 每個柱面為一個柱面組(組號與柱面號一致),一個分區包含多個柱面。
  • 配置信息:不詳。
  • i節點位圖(inode bitmap):每個inode結點對應位圖中的一個位(這樣一個字節可表示8個inode的使用情況),每個位值為0或1,表示該位所處下標對應的inode有沒有被使用。
  • 塊位圖(block bitmap):每個數據塊或目錄塊都對應着塊位圖中的一個位,位的下標和塊編號一一對應,每個位的值為0或1,表示該塊是否已被使用。
  • i節點表(數組)(inode table):每個文件或者目錄都有對應的一個inode,inode放在inode table中,包括inode的編號及其對應的信息。
  • i節點(inode): 存儲文件相關信息(不包括文件名)。
  • 數據塊(data block): 存儲文件具體內容。
  • 目錄塊: 特殊一點的數據塊,存放inode編號--文件(目錄)名

 

inode詳解

inode的主要記錄了文件的屬性以及該文件實際數據是放在哪幾號數據塊(或目錄塊)中,具體包含以下信息:

  • 文件的訪問模式(r/w/x)
  • 文件所有者和組(owner/group)
  • 文件大小
  • 文件創建或狀態改變的時間(ctime)
  • 最近一次的讀取時間(atime)
  • 最近修改的時間(mtime)
  • 定義文件特性的標志(flag)
  • 文件真正內容指向的數據塊(pointer)

另外,inode的特征有:

  • inode的數量和大小在磁盤格式化的時候就已經固定了,除非再次格式化重新設置,否則不可改變。
  • 每個inode的大小均為128Bytes。
  • 每個文件僅占用一個inode。
  • 文件系統能夠創建(存儲)的文件數量和inode的數量有關,也和磁盤大小(數據塊數量)有關。
  • 系統讀取文件時,需要先找到inode,分析inode記錄的權限與用戶是否符合,若符合才可以開始實際讀取數據塊中的內容。
  • 為了解決inode數量可能不夠用的問題,操作系統將inode記錄block號的區域定義為12個直接、1個間接、1個雙間接、1個三間接的記錄區。
  • 文件IO編程中常說的文件句柄,其實就是inode編號。

 

0x03 文件讀取過程

 已讀取文件/var/log/message為例,講解讀取文件messages時,從磁盤中查找/讀取文件內容的過程。

  1. 首先系統通過掛載信息(在超級塊中,位置固定)找到根目錄(/)的inode編號,根目錄對應的inode是固定的(通常為2號)。
  2. 根據根目錄的inode編號(2號),在inode table中找到對應的inode信息,從inode信息中找到存儲根目錄信息的目錄塊編號,根據編號找到數據塊,如圖中標記為‘/’的方格,該目錄塊存儲的信息如圖中的dentry所示。
  3. 從目錄塊中存儲的信息中,找到文件名(目錄名)為var所對應的inode編號(2667711)。
  4. 在inode table中找到編號為2667711的inode信息,從該inode信息中,找到var目錄存放的數據塊。從var數據塊存儲的信息中,找到log目錄對應的inode編號(267850)。
  5. 重復上述步驟,直至找到message文件對應的inode結點,根據inode結點中記錄的message文件內容對應的數據塊,從數據塊中讀取內容。

 

 0x04 扇區、塊(簇/數據塊)、頁

在操作系統數據交互過程中,經常聽到扇區、塊(簇/數據塊)、頁這幾種單位,他們在數據交互過程中的意義為:

  • 扇區: 磁頭從磁盤中讀取數據的最小單位,即磁頭每次從磁盤中讀取數據,都是一個扇區一個扇區讀的。
  • 塊(簇): 操作系統與磁盤(硬盤)交互的最小數據單元(在linux系統中稱為塊,在windows系統中稱為簇)。操作系統從硬盤中拿一數據,即完成一次磁盤IO。塊(數據塊)的大小在硬盤格式化時被指定,一般有1K,2K,4K(最常用)。如果塊的大小設置為4K,那么磁盤要讀取8個扇區之后,才將數據塊傳給操作系統。另外,數據塊也是DOS下數據存儲的最小單元。例如,如果一個文件的大小為1K,而塊的大小為4K,那么該文件還是會占用一個塊,塊中剩下的3K被空閑出來,不能用於存儲其他數據。因此,設置塊的大小時,需要考慮要存儲文件的大小。
  • 頁: 操作系統訪問內存時的最小單元,一般系統頁的大小為4K(或者更大)。操作系統訪問內存中的數據時,如果發現內存中沒有哪個可以提供該數據,那么會發生缺頁,系統通過頁替換(從硬盤中讀取數據)的方式,將數據從硬盤讀取到內存頁中,再返回給調用者。

總的說來,主要就是不同系統、設備間數據交互時,使用了不同的機制和概念。其中磁盤內部(磁盤驅動程序從磁盤)讀取數據時,以扇區為單位;操作系統從磁盤讀取數據時,以塊為單位;操作系統從內存讀取數據時,以頁為單位。

 

0x05 操作系統對文件存取操作的優化

並非每次讀、寫文件操作都會真正地從磁盤讀出或寫入,那樣性能難以接受。為此操作系統使用了一系列機制,提升了文件IO的性能。

緩存

不管是硬盤還是操作系統,都會對從磁盤片中讀取的數據進行緩存。硬盤中的緩存一般會比較小,如十幾M,操作系統中的緩存則可能大很多。系統會將常用的文件數據放到主存儲器的緩沖區,以加速文件系統的讀寫。一般情況下,只要系統的內存夠用,系統會盡可能多的將磁盤中常用的文件緩存到內存中,直至內存耗盡(這是正常現象)。比如,如果你發現在電腦上讀取文件的速度達到了2G每秒,那肯定不是真的從磁盤讀取的,而是從緩存讀取的。所以要測試磁盤真正的讀數據的速度,需要先清空系統的緩存。

異步處理

當系統加載一個文件到內存后,如果該文件沒有被改動過,則在內存區段的文件數據會被標記為clean,如果是被改動了,則會標記為dirty。此時所有的文件操作還是在內存中進行,並沒有寫入到磁盤中。系統會不定時的將內存中設置為dirty的數據寫回到磁盤,以保持磁盤與內存數據的一致性。這個過程是異步的。你也可以sync命令,將內存中的數強制寫回到硬盤。

另外,要注意的是,在正常關機的情況下,關機命令會主動調用sync來將內存中的數據寫入到磁盤內,但是如果非正常關機(如斷電、死機),由於數據沒有來得及寫入到磁盤,因此重新啟動可能會花費很長的時間進行磁盤檢驗,甚至可能導致文件系統的損毀(非磁盤損壞)。

 

參考

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM