最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

從內(nèi)核文件系統(tǒng)看文件讀寫過程(超詳細(xì))

2022-04-05 14:20 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

系統(tǒng)調(diào)用

  • 操作系統(tǒng)的主要功能是為管理硬件資源和為應(yīng)用程序開發(fā)人員提供良好的環(huán)境,但是計(jì)算機(jī)系統(tǒng)的各種硬件資源是有限的,因此為了保證每一個(gè)進(jìn)程都能安全的執(zhí)行。處理器設(shè)有兩種模式:“用戶模式”與“內(nèi)核模式”。一些容易發(fā)生安全問題的操作都被限制在只有內(nèi)核模式下才可以執(zhí)行,例如I/O操作,修改基址寄存器內(nèi)容等。而連接用戶模式和內(nèi)核模式的接口稱之為系統(tǒng)調(diào)用。

  • 應(yīng)用程序代碼運(yùn)行在用戶模式下,當(dāng)應(yīng)用程序需要實(shí)現(xiàn)內(nèi)核模式下的指令時(shí),先向操作系統(tǒng)發(fā)送調(diào)用請(qǐng)求。操作系統(tǒng)收到請(qǐng)求后,執(zhí)行系統(tǒng)調(diào)用接口,使處理器進(jìn)入內(nèi)核模式。當(dāng)處理器處理完系統(tǒng)調(diào)用操作后,操作系統(tǒng)會(huì)讓處理器返回用戶模式,繼續(xù)執(zhí)行用戶代碼。

  • 進(jìn)程的虛擬地址空間可分為兩部分,內(nèi)核空間和用戶空間。內(nèi)核空間中存放的是內(nèi)核代碼和數(shù)據(jù),而進(jìn)程的用戶空間中存放的是用戶程序的代碼和數(shù)據(jù)。不管是內(nèi)核空間還是用戶空間,它們都處于虛擬空間中,都是對(duì)物理地址的映射。

  • 應(yīng)用程序中實(shí)現(xiàn)對(duì)文件的操作過程就是典型的系統(tǒng)調(diào)用過程。

虛擬文件系統(tǒng)

  • 一個(gè)操作系統(tǒng)可以支持多種底層不同的文件系統(tǒng)(比如NTFS, FAT, ext3, ext4),為了給內(nèi)核和用戶進(jìn)程提供統(tǒng)一的文件系統(tǒng)視圖,Linux在用戶進(jìn)程和底層文件系統(tǒng)之間加入了一個(gè)抽象層,即虛擬文件系統(tǒng)(Virtual File System, VFS),進(jìn)程所有的文件操作都通過VFS,由VFS來適配各種底層不同的文件系統(tǒng),完成實(shí)際的文件操作。

  • 通俗的說,VFS就是定義了一個(gè)通用文件系統(tǒng)的接口層和適配層,一方面為用戶進(jìn)程提供了一組統(tǒng)一的訪問文件,目錄和其他對(duì)象的統(tǒng)一方法,另一方面又要和不同的底層文件系統(tǒng)進(jìn)行適配。如圖所示:



虛擬文件系統(tǒng)主要模塊

  1. 超級(jí)塊(super_block),用于保存一個(gè)文件系統(tǒng)的所有元數(shù)據(jù),相當(dāng)于這個(gè)文件系統(tǒng)的信息庫,為其他的模塊提供信息。因此一個(gè)超級(jí)塊可代表一個(gè)文件系統(tǒng)。文件系統(tǒng)的任意元數(shù)據(jù)修改都要修改超級(jí)塊。超級(jí)塊對(duì)象是常駐內(nèi)存并被緩存的。

  2. 目錄項(xiàng)模塊,管理路徑的目錄項(xiàng)。比如一個(gè)路徑 /home/foo/hello.txt,那么目錄項(xiàng)有home, foo, hello.txt。目錄項(xiàng)的塊,存儲(chǔ)的是這個(gè)目錄下的所有的文件的inode號(hào)和文件名等信息。其內(nèi)部是樹形結(jié)構(gòu),操作系統(tǒng)檢索一個(gè)文件,都是從根目錄開始,按層次解析路徑中的所有目錄,直到定位到文件。

  3. inode模塊,管理一個(gè)具體的文件,是文件的唯一標(biāo)識(shí),一個(gè)文件對(duì)應(yīng)一個(gè)inode。通過inode可以方便的找到文件在磁盤扇區(qū)的位置。同時(shí)inode模塊可鏈接到address_space模塊,方便查找自身文件數(shù)據(jù)是否已經(jīng)緩存。

  4. 打開文件列表模塊,包含所有內(nèi)核已經(jīng)打開的文件。已經(jīng)打開的文件對(duì)象由open系統(tǒng)調(diào)用在內(nèi)核中創(chuàng)建,也叫文件句柄。打開文件列表模塊中包含一個(gè)列表,每個(gè)列表表項(xiàng)是一個(gè)結(jié)構(gòu)體struct file,結(jié)構(gòu)體中的信息用來表示打開的一個(gè)文件的各種狀態(tài)參數(shù)。

  5. file_operations模塊。這個(gè)模塊中維護(hù)一個(gè)數(shù)據(jù)結(jié)構(gòu),是一系列函數(shù)指針的集合,其中包含所有可以使用的系統(tǒng)調(diào)用函數(shù),例如open、read、write、mmap等。每個(gè)打開文件(打開文件列表模塊的一個(gè)表項(xiàng))都可以連接到file_operations模塊,從而對(duì)任何已打開的文件,通過系統(tǒng)調(diào)用函數(shù),實(shí)現(xiàn)各種操作。

  6. address_space模塊,它表示一個(gè)文件在頁緩存中已經(jīng)緩存了的物理頁。它是頁緩存和外部設(shè)備中文件系統(tǒng)的橋梁。如果將文件系統(tǒng)可以理解成數(shù)據(jù)源,那么address_space可以說關(guān)聯(lián)了內(nèi)存系統(tǒng)和文件系統(tǒng)。我們會(huì)在文章后面繼續(xù)討論。

  • 模塊間的相互作用和邏輯關(guān)系如下圖所示:

【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。?!前100名進(jìn)群領(lǐng)取,額外贈(zèng)送一份價(jià)值699的內(nèi)核資料包(含視頻教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)?


  • 由圖可以看出:

  1. 每個(gè)模塊都維護(hù)了一個(gè)X_op指針指向它所對(duì)應(yīng)的操作對(duì)象X_operations。

  2. 超級(jí)塊維護(hù)了一個(gè)s_files指針指向了“已打開文件列表模塊”,即內(nèi)核所有的打開文件的鏈表,這個(gè)鏈表信息是所有進(jìn)程共享的。

  3. 目錄操作模塊和inode模塊都維護(hù)了一個(gè)X_sb指針指向超級(jí)塊,從而可以獲得整個(gè)文件系統(tǒng)的元數(shù)據(jù)信息。

  4. 目錄項(xiàng)對(duì)象和inode對(duì)象各自維護(hù)了指向?qū)Ψ降闹羔?,可以找到?duì)方的數(shù)據(jù)。

  5. 已打開文件列表上每一個(gè)file結(jié)構(gòu)體實(shí)例維護(hù)了一個(gè)f_dentry指針,指向了它對(duì)應(yīng)的目錄項(xiàng),從而可以根據(jù)目錄項(xiàng)找到它對(duì)應(yīng)的inode信息。

  6. 已打開文件列表上每一個(gè)file結(jié)構(gòu)體實(shí)例維護(hù)了一個(gè)f_op指針,指向可以對(duì)這個(gè)文件進(jìn)行操作的所有函數(shù)集合file_operations。

  7. inode中不僅有和其他模塊關(guān)聯(lián)的指針,重要的是它可以指向address_space模塊,從而獲得自身文件在內(nèi)存中的緩存信息。

  8. address_space內(nèi)部維護(hù)了一個(gè)樹結(jié)構(gòu)來指向所有的物理頁結(jié)構(gòu)page,同時(shí)維護(hù)了一個(gè)host指針指向inode來獲得文件的元數(shù)據(jù)。

進(jìn)程和虛擬文件系統(tǒng)交互

  1. 內(nèi)核使用task_struct來表示單個(gè)進(jìn)程的描述符,其中包含維護(hù)一個(gè)進(jìn)程的所有信息。task_struct結(jié)構(gòu)體中維護(hù)了一個(gè) files的指針(和“已打開文件列表”上的表項(xiàng)是不同的指針)來指向結(jié)構(gòu)體files_struct,files_struct中包含文件描述符表和打開的文件對(duì)象信息。

  2. file_struct中的文件描述符表實(shí)際是一個(gè)file類型的指針列表(和“已打開文件列表”上的表項(xiàng)是相同的指針),可以支持動(dòng)態(tài)擴(kuò)展,每一個(gè)指針指向虛擬文件系統(tǒng)中文件列表模塊的某一個(gè)已打開的文件。



3. file結(jié)構(gòu)一方面可從f_dentry鏈接到目錄項(xiàng)模塊以及inode模塊,獲取所有和文件相關(guān)的信息,另一方面鏈接file_operations子模塊,其中包含所有可以使用的系統(tǒng)調(diào)用函數(shù),從而最終完成對(duì)文件的操作。這樣,從進(jìn)程到進(jìn)程的文件描述符表,再關(guān)聯(lián)到已打開文件列表上對(duì)應(yīng)的文件結(jié)構(gòu),從而調(diào)用其可執(zhí)行的系統(tǒng)調(diào)用函數(shù),實(shí)現(xiàn)對(duì)文件的各種操作。

進(jìn)程 vs 文件列表 vs Inode

  1. 多個(gè)進(jìn)程可以同時(shí)指向一個(gè)打開文件對(duì)象(文件列表表項(xiàng)),例如父進(jìn)程和子進(jìn)程間共享文件對(duì)象;

  2. 一個(gè)進(jìn)程可以多次打開一個(gè)文件,生成不同的文件描述符,每個(gè)文件描述符指向不同的文件列表表項(xiàng)。但是由于是同一個(gè)文件,inode唯一,所以這些文件列表表項(xiàng)都指向同一個(gè)inode。通過這樣的方法實(shí)現(xiàn)文件共享(共享同一個(gè)磁盤文件);

I/O 緩沖區(qū)

概念

  • 如高速緩存(cache)產(chǎn)生的原理類似,在I/O過程中,讀取磁盤的速度相對(duì)內(nèi)存讀取速度要慢的多。因此為了能夠加快處理數(shù)據(jù)的速度,需要將讀取過的數(shù)據(jù)緩存在內(nèi)存里。而這些緩存在內(nèi)存里的數(shù)據(jù)就是高速緩沖區(qū)(buffer cache),下面簡稱為“buffer”。

  • 具體來說,buffer(緩沖區(qū))是一個(gè)用于存儲(chǔ)速度不同步的設(shè)備或優(yōu)先級(jí)不同的設(shè)備之間傳輸數(shù)據(jù)的區(qū)域。一方面,通過緩沖區(qū),可以使進(jìn)程之間的相互等待變少,從而使從速度慢的設(shè)備讀入數(shù)據(jù)時(shí),速度快的設(shè)備的操作進(jìn)程不發(fā)生間斷。另一方面,可以保護(hù)硬盤或減少網(wǎng)絡(luò)傳輸?shù)拇螖?shù)。

Buffer和Cache

  • buffer和cache是兩個(gè)不同的概念:cache是高速緩存,用于CPU和內(nèi)存之間的緩沖;buffer是I/O緩存,用于內(nèi)存和硬盤的緩沖;簡單的說,cache是加速“讀”,而buffer是緩沖“寫”,前者解決讀的問題,保存從磁盤上讀出的數(shù)據(jù),后者是解決寫的問題,保存即將要寫入到磁盤上的數(shù)據(jù)。

Buffer Cache和 Page Cache

  • buffer cache和page cache都是為了處理設(shè)備和內(nèi)存交互時(shí)高速訪問的問題。buffer cache可稱為塊緩沖器,page cache可稱為頁緩沖器。在linux不支持虛擬內(nèi)存機(jī)制之前,還沒有頁的概念,因此緩沖區(qū)以塊為單位對(duì)設(shè)備進(jìn)行。在linux采用虛擬內(nèi)存的機(jī)制來管理內(nèi)存后,頁是虛擬內(nèi)存管理的最小單位,開始采用頁緩沖的機(jī)制來緩沖內(nèi)存。Linux2.6之后內(nèi)核將這兩個(gè)緩存整合,頁和塊可以相互映射,同時(shí),頁緩存page cache面向的是虛擬內(nèi)存,塊I/O緩存Buffer cache是面向塊設(shè)備。需要強(qiáng)調(diào)的是,頁緩存和塊緩存對(duì)進(jìn)程來說就是一個(gè)存儲(chǔ)系統(tǒng),進(jìn)程不需要關(guān)注底層的設(shè)備的讀寫。

  • buffer cache和page cache兩者最大的區(qū)別是緩存的粒度。buffer cache面向的是文件系統(tǒng)的塊。而內(nèi)核的內(nèi)存管理組件采用了比文件系統(tǒng)的塊更高級(jí)別的抽象:頁page,其處理的性能更高。因此和內(nèi)存管理交互的緩存組件,都使用頁緩存。

Page Cache

  • 頁緩存是面向文件,面向內(nèi)存的。通俗來說,它位于內(nèi)存和文件之間緩沖區(qū),文件IO操作實(shí)際上只和page cache交互,不直接和內(nèi)存交互。page cache可以用在所有以文件為單元的場(chǎng)景下,比如網(wǎng)絡(luò)文件系統(tǒng)等等。page cache通過一系列的數(shù)據(jù)結(jié)構(gòu),比如inode, address_space, struct page,實(shí)現(xiàn)將一個(gè)文件映射到頁的級(jí)別:

1.struct page結(jié)構(gòu)標(biāo)志一個(gè)物理內(nèi)存頁,通過page + offset就可以將此頁幀定位到一個(gè)文件中的具體位置。同時(shí)struct page還有以下重要參數(shù):

(1)標(biāo)志位flags來記錄該頁是否是臟頁,是否正在被寫回等等;

(2)mapping指向了地址空間address_space,表示這個(gè)頁是一個(gè)頁緩存中頁,和一個(gè)文件的地址空間對(duì)應(yīng);

(3)index記錄這個(gè)頁在文件中的頁偏移量;

2. 文件系統(tǒng)的inode實(shí)際維護(hù)了這個(gè)文件所有的塊block的塊號(hào),通過對(duì)文件偏移量offset取??梢院芸於ㄎ坏竭@個(gè)偏移量所在的文件系統(tǒng)的塊號(hào),磁盤的扇區(qū)號(hào)。同樣,通過對(duì)文件偏移量offset進(jìn)行取??梢杂?jì)算出偏移量所在的頁的偏移量。

3. page cache緩存組件抽象了地址空間address_space這個(gè)概念來作為文件系統(tǒng)和頁緩存的中間橋梁。地址空間address_space通過指針可以方便的獲取文件inode和struct page的信息,所以可以很方便地定位到一個(gè)文件的offset在各個(gè)組件中的位置,即通過:文件字節(jié)偏移量 --> 頁偏移量 --> 文件系統(tǒng)塊號(hào) block ?--> ?磁盤扇區(qū)號(hào)

4. 頁緩存實(shí)際上就是采用了一個(gè)基數(shù)樹結(jié)構(gòu)將一個(gè)文件的內(nèi)容組織起來存放在物理內(nèi)存struct page中。一個(gè)文件inode對(duì)應(yīng)一個(gè)地址空間address_space。而一個(gè)address_space對(duì)應(yīng)一個(gè)頁緩存基數(shù)樹。它們之間的關(guān)系如下:



Address Space

  • 下面我們總結(jié)已經(jīng)討論過的address_space所有功能。address_space是Linux內(nèi)核中的一個(gè)關(guān)鍵抽象,它被作為文件系統(tǒng)和頁緩存的中間適配器,用來指示一個(gè)文件在頁緩存中已經(jīng)緩存了的物理頁。因此,它是頁緩存和外部設(shè)備中文件系統(tǒng)的橋梁。如果將文件系統(tǒng)可以理解成數(shù)據(jù)源,那么address_space可以說關(guān)聯(lián)了內(nèi)存系統(tǒng)和文件系統(tǒng)。


  • 由圖中可以看到,地址空間address_space鏈接到頁緩存基數(shù)樹和inode,因此address_space通過指針可以方便的獲取文件inode和page的信息。那么頁緩存是如何通過address_space實(shí)現(xiàn)緩沖區(qū)功能的?我們?cè)賮砜赐暾奈募x寫流程。

文件讀寫基本流程

讀文件

  1. 進(jìn)程調(diào)用庫函數(shù)向內(nèi)核發(fā)起讀文件請(qǐng)求;

  2. 內(nèi)核通過檢查進(jìn)程的文件描述符定位到虛擬文件系統(tǒng)的已打開文件列表表項(xiàng);

  3. 調(diào)用該文件可用的系統(tǒng)調(diào)用函數(shù)read()

  4. read()函數(shù)通過文件表項(xiàng)鏈接到目錄項(xiàng)模塊,根據(jù)傳入的文件路徑,在目錄項(xiàng)模塊中檢索,找到該文件的inode;

  5. 在inode中,通過文件內(nèi)容偏移量計(jì)算出要讀取的頁;

  6. 通過inode找到文件對(duì)應(yīng)的address_space;

  7. 在address_space中訪問該文件的頁緩存樹,查找對(duì)應(yīng)的頁緩存結(jié)點(diǎn):

(1)如果頁緩存命中,那么直接返回文件內(nèi)容;

(2)如果頁緩存缺失,那么產(chǎn)生一個(gè)頁缺失異常,創(chuàng)建一個(gè)頁緩存頁,同時(shí)通過inode找到文件該頁的磁盤地址,讀取相應(yīng)的頁填充該緩存頁;重新進(jìn)行第6步查找頁緩存;

8. 文件內(nèi)容讀取成功。

寫文件

  • 前5步和讀文件一致,在address_space中查詢對(duì)應(yīng)頁的頁緩存是否存在:

6. 如果頁緩存命中,直接把文件內(nèi)容修改更新在頁緩存的頁中。寫文件就結(jié)束了。這時(shí)候文件修改位于頁緩存,并沒有寫回到磁盤文件中去。

7. 如果頁緩存缺失,那么產(chǎn)生一個(gè)頁缺失異常,創(chuàng)建一個(gè)頁緩存頁,同時(shí)通過inode找到文件該頁的磁盤地址,讀取相應(yīng)的頁填充該緩存頁。此時(shí)緩存頁命中,進(jìn)行第6步。

8. 一個(gè)頁緩存中的頁如果被修改,那么會(huì)被標(biāo)記成臟頁。臟頁需要寫回到磁盤中的文件塊。有兩種方式可以把臟頁寫回磁盤:

(1)手動(dòng)調(diào)用sync()或者fsync()系統(tǒng)調(diào)用把臟頁寫回

(2)pdflush進(jìn)程會(huì)定時(shí)把臟頁寫回到磁盤

  • 同時(shí)注意,臟頁不能被置換出內(nèi)存,如果臟頁正在被寫回,那么會(huì)被設(shè)置寫回標(biāo)記,這時(shí)候該頁就被上鎖,其他寫請(qǐng)求被阻塞直到鎖釋放。




從內(nèi)核文件系統(tǒng)看文件讀寫過程(超詳細(xì))的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
墨竹工卡县| 图片| 丰宁| 金堂县| 随州市| 南丹县| 通榆县| 静宁县| 铜陵市| 海林市| 什邡市| 荆州市| 嵩明县| 高清| 灵寿县| 南京市| 双峰县| 大理市| 河间市| 锡林郭勒盟| 泗阳县| 仪征市| 固安县| 金阳县| 年辖:市辖区| 建平县| 黄浦区| 枣强县| 桂东县| 宿州市| 乐山市| 行唐县| 上犹县| 罗城| 陈巴尔虎旗| 依兰县| 和政县| 金溪县| 江津市| 仁寿县| 盐山县|