Linux 0.11原始碼閱讀筆記-檔案管理
檔案系統
生磁盤
未安裝檔案系統的磁盤稱之為生磁盤,生磁盤也可以作為檔案讀寫,linux中一切皆檔案,
磁盤磁區
生磁盤可以被磁區,磁區中可以安裝檔案系統,常見的檔案系統有fat32、ext2、ext4等,磁區后的磁盤結構布局如下圖,其中主引導扇區記錄了磁區資訊,并且包含引導代碼可用于引導作業系統,

檔案系統
磁區內可以安裝指定檔案系統,同一磁盤多個磁區檔案系統不要求相同,MINIX檔案系統布局如下:

- 引導塊:若作為引導磁區,將存放作業系統的引導程式代碼,否則空置,
- 超級塊:用于存放磁盤設備上檔案系統結構的資訊,說明各部分的大小,
- i節點位圖:標記i節點資料元素是否被使用
- 邏輯塊位圖:標記磁盤資料塊是否被使用
- i節點區:用于存放inode節點資料,一個檔案對應一個inode節點,inode節點存盤檔案屬性資料,
- 資料區:以固定大小盤塊(1k)為單位進行動態分配和回收,用于存盤資料,類似記憶體分頁,
超級塊
用于存放磁盤設備上檔案系統結構的資訊,說明各部分的大小,
圖中列出的資料包含兩部分:出現在盤上和記憶體中的欄位和僅在記憶體中使用的欄位,僅在記憶體中使用的欄位是內核讀取超級塊后所附加的一些用于管理使用的欄位資訊,

inode節點
inode節點保存對應檔案的屬性資訊,其中i_zone陣列使用類似多級頁表的方式維護檔案資料塊,即記錄檔案邏輯塊到物理塊之間的映射關系,

i_zone陣列
i_zone陣列包含直接盤塊號、一次間接盤塊號和二次間接盤塊號,一次盤塊號可視為單級頁表,一次間接盤塊號可視為二級頁表、二次間接盤塊號可視為三級頁表,
這種處理方式的好處在于,對于小檔案,通過直接塊號可快速定位資料塊;對于中等型別的檔案,一次間接塊可以維護較多資料塊的同時,具有較快的訪問速度;對于大型檔案,二次間接盤塊號可以維護大量磁盤塊,但訪問速度較慢,
記憶體多級頁表與i_zone直接區別:不同行程具有固定大小的虛地址空間,并且對其整個虛地址空間的記憶體,都有可能訪問到,因此使用多級頁表,檔案系統記憶體在很多大小不一的檔案,綜合考慮對不同大小檔案的特點,使用1-3級磁盤塊表可以分別處理小、中、大檔案,

目錄結構
- 樹形目錄結構
檔案系統目錄結構為樹形,根節點為根目錄,目錄可以指向若干個子目錄或子檔案,

- 檔案查找程序
通過檔案inode節點,可以定位檔案資料塊,那如何通過檔案路徑定位到具體檔案?
檔案系統主要包含檔案和目錄兩種檔案,目錄是一種特殊的檔案,其檔案內容存盤其目錄下檔案名->inode節點號的映射資訊,檔案查找開始于根目錄,根目錄號固定為0,不需要查找即可直接打開,
舉例說明檔案查找程序,給定存在路徑/name1/name2/name3查找具體檔案程序:
1)通過根節點inode號,打開根目錄,讀取其檔案內容,即目錄下檔案名->inode節點號映射表,找到name1目錄inode節點號n1
2)通過name1的inode號n1,打開name1目錄,讀取其檔案內容,即目錄下檔案名->inode節點號映射表,找到name1目錄inode節點號n2
3)通過name2的inode號n2,打開name2目錄,讀取其檔案內容,即目錄下檔案名->inode節點號映射表,找到name3目錄inode節點號n3
4)通過name3的inode號n3,打開name3檔案
- 檔案資料塊定位程序
1)打開檔案:先通過檔案查找找到檔案inode節點號,然后打開檔案,即讀取inode至記憶體,
2)定位資料塊:通過檔案inode節點,訪問其i_zone陣列,進一步可以定位具體的資料所在磁盤塊號,

檔案鏈接
- 硬鏈接
硬鏈接,在指定目錄檔案中,生成一個檔案,即建立檔案名->inode節點號的映射,不同之處在于,硬鏈接檔案的inode號是其它檔案的inode號,即多個檔案共享一個inode,多個檔案共享inode節點時,會引起inode節點參考計數增加,
硬鏈接示意圖如下,

- 軟鏈接(符號鏈接)
軟鏈接,在指定目錄檔案中,生成一個檔案,建立檔案名->檔案路徑的映射,軟鏈接檔案項不直接指向被指向檔案的inode號,而是記錄其檔案路徑,符號鏈接不直接共享inode,不會引起inode節點參考計數增加,
打開軟鏈接檔案時,先獲取其指向的檔案路徑,再通過指向的檔案路徑打開檔案,
軟鏈接檔案示意圖如下,其中藍色線表示軟鏈接,

- 洗掉被鏈接檔案
硬鏈接:多個檔案指向同一個inode節點,參考計數等于檔案數量,洗掉其中一個檔案,只會導致參考計數減小1,參考計數為零時,檔案才會被洗掉,
軟鏈接:洗掉軟鏈接,不會對被指向檔案產生任何影響;洗掉被指向檔案,軟鏈接可能會失效,
高速快取
高速快取是內核訪問磁盤檔案系統資料的必經之道,高速快取用于解決CPU速度與磁盤IO速度不匹配的問題,因為CPU速度與磁盤IO速度差距較大,CPU同步讀寫磁盤資料,會導致CPU性能的浪費,
內核維護一個高速緩沖區池,按塊使用和管理,可用于快取磁盤資料,提高訪問磁盤資料的性能,
buffer.c檔案包含實作高速緩沖區的程式,內核代碼通過指定設備號和邏輯塊號來呼叫塊讀寫函式,這些介面函式有,bread()、breada()、bread_page(),
- bread:塊讀取函式
- breada:塊提前預讀函式
- bread_page:頁塊讀取函式,一個記憶體頁通常為4k大小、磁盤塊通常為1k大小
檔案系統相關函式
檔案系統底層函式
該部分函式用于處理檔案系統的元資料,包括超級塊、位圖、inode節點等,該部分函式被內核其它部分代碼呼叫,不是提供給用戶代碼呼叫的系統呼叫介面,
檔案系統底層處理函式包含在以下5個檔案中:
-
bitmap.c:包含對i節點位圖和邏輯塊位圖進行釋放和占用處理函式,free_inode()、new_inode()、free_block()、new_block()
-
truncate.c:對資料檔案長度截斷為0的函式truncate(),可釋放檔案所有資料塊,
-
inode.c:包含分配釋放inode節點函式iget()和iput(),以及根據inode節點,獲取檔案邏輯塊號函式bmap(),
-
namei.c:包含函式namei(),獲取指定路徑的inode節點
-
super.c:包的程式專門用于處理系統超級塊,包括函式get_super()、free_super()等,還包括幾個檔案系統加載/卸載處理函式和系統呼叫,如sys_mount()等,
下圖展示了檔案系統不同部分對應的底層處理函式:

檔案中資料的訪問操作
該部分函式用于處理檔案的讀、寫操作,
- 檔案資料訪問函式
用戶程式呼叫read()、write()函式讀寫檔案,read()、write()函式根據檔案型別與其所在設備,進一步呼叫設備對應的讀寫函式如read_pipe()、write_pipe()等,

- 打開檔案使用的內核資料結構
內核使用檔案結構file、檔案表file_table[]和記憶體中的i節點表inode_table[]來管理對檔案的操作訪問,
- 檔案指標陣列,行程使用一個檔案指標陣列管理打開的檔案,其中的檔案指標(下標號)指向檔案表中對應的檔案結構file,每個行程有自己的檔案指標陣列,
- 檔案表:表項為file資料,用于在檔案句柄于記憶體i節點項之間建立關系,其包含檔案型別、訪問屬性、讀寫指標、檔案句柄參考計數等資訊,因為不同行程可能使用不同的訪問模式打開同一檔案,并且需要單獨的讀寫指標等資料,所有行程共享檔案表(file_table),
- 記憶體i節點表:表項存盤i節點資訊,存盤所有行程打開檔案的i節點資訊,所有行程共享記憶體i節點表,
思考:檔案描述符指向file結構、file結構指向記憶體inode節點,允許存在多對一的情況,什么場景會存在多個檔案描述符指向同一個file結構;什么場景存在多個file結構指向同一個記憶體inode節點,
open同一個檔案:多個file資料指向同一inode節點
dul同一檔案描述符:多個檔案描述符指向同一檔案表項—file資料,
fork行程:僅復制檔案描述符表
內核資料結構

file資料結構

檔案和目錄管理系統呼叫
- open.c:實作檔案管理相關的系統呼叫,主要包括創建、打開、關閉和屬性修改,
- exec.c:實作對二進制可執行檔案和shell腳本檔案的加載與執行,其中主要的函式為do_execve(),是exec()函式簇的主要實作函式,
- fcntl.c:實作檔案系統控制呼叫fcntl()和檔案描述符的復制系統呼叫dup()、dup2(),dup主要用于多個檔案描述符指向同一file結構的場景,
- ioctl.c:實作輸入/輸出控制系統呼叫ioctl,主要呼叫tty_ioctl()函式,對終端io進行控制,
- stat.c:實作取檔案狀態資訊系統呼叫stat()和fstat,

總結
- MINIX檔案系統空閑inode節點項和空閑磁盤塊均通過位圖管理,位圖記錄對應項是否空閑,
- 硬鏈接和軟鏈接的區別在于,鏈接是直接指向inde節點,還是通過指向其他檔案路徑間接指向inode節點,
- linux內核具有io高速緩沖區,用于快取磁盤資料,提高磁盤資料的訪問效率,
- 打開檔案內核資料結構具有三級映射關系:檔案描述符->file資料->記憶體inode節點,open同一檔案,多個file指向同一記憶體inode;dup檔案描述符,多個檔案描述符指向同一file,
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/455364.html
標籤:Linux
