精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

吐血整理 | 肝翻Linux文件系統(tǒng)所有知識點(diǎn)

系統(tǒng) Linux
內(nèi)核參數(shù)是用戶和系統(tǒng)內(nèi)核之間交互的一個接口,通過這個接口,用戶可以在系統(tǒng)運(yùn)行的同時動態(tài)更新內(nèi)核配置,而這些內(nèi)核參數(shù)是通過Linux Proc文件系統(tǒng)存在的。因此,可以通過調(diào)整Proc文件系統(tǒng)達(dá)到優(yōu)化Linux性能的目的。

在 Linux 操作系統(tǒng)的廣袤天地里,文件系統(tǒng)宛如一座錯綜復(fù)雜而又井然有序的知識寶庫,蘊(yùn)藏著無數(shù)的奧秘與智慧。從我們?nèi)粘?chuàng)建、讀取和保存文件,到整個系統(tǒng)的高效存儲管理與數(shù)據(jù)組織,Linux 文件系統(tǒng)都在背后默默地發(fā)揮著關(guān)鍵作用。Linux系統(tǒng)一般有4個主要部分:內(nèi)核、shell、文件系統(tǒng)和應(yīng)用程序。內(nèi)核、shell和文件系統(tǒng)一起形成了基本的操作系統(tǒng)結(jié)構(gòu),它們使得用戶可以運(yùn)行程序、管理文件并使用系統(tǒng)。

它就像是一位無聲的管理者,精心安排著數(shù)據(jù)在磁盤上的存放位置,巧妙地構(gòu)建起目錄與文件之間的層級關(guān)系,確保我們能夠迅速而準(zhǔn)確地找到所需的信息。無論是對于初涉 Linux 領(lǐng)域的新手,渴望了解其基礎(chǔ)的文件操作原理;還是經(jīng)驗豐富的系統(tǒng)管理員,需要深入探究文件系統(tǒng)的優(yōu)化與故障排查技巧;又或是開發(fā)者,試圖在應(yīng)用程序中高效地與文件系統(tǒng)交互,掌握 Linux 文件系統(tǒng)的知識都至關(guān)重要。

一、Linux內(nèi)核

內(nèi)核是操作系統(tǒng)的核心,具有很多最基本功能,它負(fù)責(zé)管理系統(tǒng)的進(jìn)程、內(nèi)存、設(shè)備驅(qū)動程序、文件和網(wǎng)絡(luò)系統(tǒng),決定著系統(tǒng)的性能和穩(wěn)定性。Linux 內(nèi)核由如下幾部分組成:內(nèi)存管理、進(jìn)程管理、設(shè)備驅(qū)動程序、文件系統(tǒng)和網(wǎng)絡(luò)管理等。如圖:

圖片圖片

系統(tǒng)調(diào)用接口:SCI 層提供了某些機(jī)制執(zhí)行從用戶空間到內(nèi)核的函數(shù)調(diào)用。這個接口依賴于體系結(jié)構(gòu),甚至在相同的處理器家族內(nèi)也是如此。SCI 實際上是一個非常有用的函數(shù)調(diào)用多路復(fù)用和多路分解服務(wù)。在 ./linux/kernel 中您可以找到 SCI 的實現(xiàn),并在 ./linux/arch 中找到依賴于體系結(jié)構(gòu)的部分。

1.1內(nèi)存管理

對任何一臺計算機(jī)而言,其內(nèi)存以及其它資源都是有限的。為了讓有限的物理內(nèi)存滿足應(yīng)用程序?qū)?nèi)存的大需求量,Linux 采用了稱為“虛擬內(nèi)存”的內(nèi)存管理方式。Linux 將內(nèi)存劃分為容易處理的“內(nèi)存頁”(對于大部分體系結(jié)構(gòu)來說都是 4KB)。Linux 包括了管理可用內(nèi)存的方式,以及物理和虛擬映射所使用的硬件機(jī)制。

不過內(nèi)存管理要管理的可不止 4KB 緩沖區(qū)。Linux 提供了對 4KB 緩沖區(qū)的抽象,例如 slab 分配器。這種內(nèi)存管理模式使用 4KB 緩沖區(qū)為基數(shù),然后從中分配結(jié)構(gòu),并跟蹤內(nèi)存頁使用情況,比如哪些內(nèi)存頁是滿的,哪些頁面沒有完全使用,哪些頁面為空。這樣就允許該模式根據(jù)系統(tǒng)需要來動態(tài)調(diào)整內(nèi)存使用。為了支持多個用戶使用內(nèi)存,有時會出現(xiàn)可用內(nèi)存被消耗光的情況。

由于這個原因,頁面可以移出內(nèi)存并放入磁盤中。這個過程稱為交換,因為頁面會被從內(nèi)存交換到硬盤上。內(nèi)存管理的源代碼可以在 ./linux/mm 中找到。

1.2進(jìn)程管理

進(jìn)程實際是某特定應(yīng)用程序的一個運(yùn)行實體。在 Linux 系統(tǒng)中,能夠同時運(yùn)行多個進(jìn)程,Linux 通過在短的時間間隔內(nèi)輪流運(yùn)行這些進(jìn)程而實現(xiàn)“多任務(wù)”。這一短的時間間隔稱為“時間片”,讓進(jìn)程輪流運(yùn)行的方法稱為“進(jìn)程調(diào)度” ,完成調(diào)度的程序稱為調(diào)度程序。進(jìn)程調(diào)度控制進(jìn)程對CPU的訪問。

當(dāng)需要選擇下一個進(jìn)程運(yùn)行時,由調(diào)度程序選擇最值得運(yùn)行的進(jìn)程。可運(yùn)行進(jìn)程實際上是僅等待CPU資源的進(jìn)程,如果某個進(jìn)程在等待其它資源,則該進(jìn)程是不可運(yùn)行進(jìn)程。Linux使用了比較簡單的基于優(yōu)先級的進(jìn)程調(diào)度算法選擇新的進(jìn)程。通過多任務(wù)機(jī)制,每個進(jìn)程可認(rèn)為只有自己獨(dú)占計算機(jī),從而簡化程序的編寫。每個進(jìn)程有自己單獨(dú)的地址空間,并且只能由這一進(jìn)程訪問,這樣,操作系統(tǒng)避免了進(jìn)程之間的互相干擾以及“壞”程序?qū)ο到y(tǒng)可能造成的危害。

為了完成某特定任務(wù),有時需要綜合兩個程序的功能,例如一個程序輸出文本,而另一個程序?qū)ξ谋具M(jìn)行排序。為此,操作系統(tǒng)還提供進(jìn)程間的通訊機(jī)制來幫助完成這樣的任務(wù)。Linux 中常見的進(jìn)程間通訊機(jī)制有信號、管道、共享內(nèi)存、信號量和套接字等。

內(nèi)核通過 SCI 提供了一個應(yīng)用程序編程接口(API)來創(chuàng)建一個新進(jìn)程(fork、exec 或 Portable Operating System Interface [POSⅨ] 函數(shù)),停止進(jìn)程(kill、exit),并在它們之間進(jìn)行通信和同步(signal 或者 POSⅨ 機(jī)制)。

1.3文件系統(tǒng)

和 DOS 等操作系統(tǒng)不同,Linux 操作系統(tǒng)中單獨(dú)的文件系統(tǒng)并不是由驅(qū)動器號或驅(qū)動器名稱(如 A: 或 C: 等)來標(biāo)識的。相反,和 UNIX 操作系統(tǒng)一樣,Linux 操作系統(tǒng)將獨(dú)立的文件系統(tǒng)組合成了一個層次化的樹形結(jié)構(gòu),并且由一個單獨(dú)的實體代表這一文件系統(tǒng)。

Linux 將新的文件系統(tǒng)通過一個稱為“掛裝”或“掛上”的操作將其掛裝到某個目錄上,從而讓不同的文件系統(tǒng)結(jié)合成為一個整體。Linux 操作系統(tǒng)的一個重要特點(diǎn)是它支持許多不同類型的文件系統(tǒng)。

Linux 中最普遍使用的文件系統(tǒng)是 Ext2,它也是 Linux 土生土長的文件系統(tǒng)。但 Linux 也能夠支持 FAT、VFAT、FAT32、MINIX 等不同類型的文件系統(tǒng),從而可以方便地和其它操作系統(tǒng)交換數(shù)據(jù)。

由于 Linux 支持許多不同的文件系統(tǒng),并且將它們組織成了一個統(tǒng)一的虛擬文件系統(tǒng).虛擬文件系統(tǒng)(VirtualFileSystem,VFS):隱藏了各種硬件的具體細(xì)節(jié),把文件系統(tǒng)操作和不同文件系統(tǒng)的具體實現(xiàn)細(xì)節(jié)分離了開來,為所有的設(shè)備提供了統(tǒng)一的接口,VFS提供了多達(dá)數(shù)十種不同的文件系統(tǒng)。

虛擬文件系統(tǒng)可以分為邏輯文件系統(tǒng)和設(shè)備驅(qū)動程序。邏輯文件系統(tǒng)指Linux所支持的文件系統(tǒng),如ext2,fat等,設(shè)備驅(qū)動程序指為每一種硬件控制器所編寫的設(shè)備驅(qū)動程序模塊。虛擬文件系統(tǒng)(VFS)是 Linux 內(nèi)核中非常有用的一個方面,因為它為文件系統(tǒng)提供了一個通用的接口抽象。

VFS 在 SCI 和內(nèi)核所支持的文件系統(tǒng)之間提供了一個交換層。即VFS 在用戶和文件系統(tǒng)之間提供了一個交換層。

在 VFS 上面,是對諸如 open、close、read 和 write 之類的函數(shù)的一個通用 API 抽象。在 VFS 下面是文件系統(tǒng)抽象,它定義了上層函數(shù)的實現(xiàn)方式。它們是給定文件系統(tǒng)(超過 50 個)的插件。

文件系統(tǒng)的源代碼可以在 ./linux/fs 中找到。文件系統(tǒng)層之下是緩沖區(qū)緩存,它為文件系統(tǒng)層提供了一個通用函數(shù)集(與具體文件系統(tǒng)無關(guān))。這個緩存層通過將數(shù)據(jù)保留一段時間(或者隨即預(yù)先讀取數(shù)據(jù)以便在需要是就可用)優(yōu)化了對物理設(shè)備的訪問。

緩沖區(qū)緩存之下是設(shè)備驅(qū)動程序,它實現(xiàn)了特定物理設(shè)備的接口。因此,用戶和進(jìn)程不需要知道文件所在的文件系統(tǒng)類型,而只需要象使用 Ext2 文件系統(tǒng)中的文件一樣使用它們。

1.4設(shè)備驅(qū)動程序

設(shè)備驅(qū)動程序是 Linux 內(nèi)核的主要部分。和操作系統(tǒng)的其它部分類似,設(shè)備驅(qū)動程序運(yùn)行在高特權(quán)級的處理器環(huán)境中,從而可以直接對硬件進(jìn)行操作,但正因為如此,任何一個設(shè)備驅(qū)動程序的錯誤都可能導(dǎo)致操作系統(tǒng)的崩潰。

設(shè)備驅(qū)動程序?qū)嶋H控制操作系統(tǒng)和硬件設(shè)備之間的交互。設(shè)備驅(qū)動程序提供一組操作系統(tǒng)可理解的抽象接口完成和操作系統(tǒng)之間的交互,而與硬件相關(guān)的具體操作細(xì)節(jié)由設(shè)備驅(qū)動程序完成。一般而言,設(shè)備驅(qū)動程序和設(shè)備的控制芯片有關(guān),例如,如果計算機(jī)硬盤是 SCSI 硬盤,則需要使用 SCSI 驅(qū)動程序,而不是 IDE 驅(qū)動程序。

1.5網(wǎng)絡(luò)接口(NET)

提供了對各種網(wǎng)絡(luò)標(biāo)準(zhǔn)的存取和各種網(wǎng)絡(luò)硬件的支持。網(wǎng)絡(luò)接口可分為網(wǎng)絡(luò)協(xié)議和網(wǎng)絡(luò)驅(qū)動程序。網(wǎng)絡(luò)協(xié)議部分負(fù)責(zé)實現(xiàn)每一種可能的網(wǎng)絡(luò)傳輸協(xié)議。眾所周知,TCP/IP 協(xié)議是 Internet 的標(biāo)準(zhǔn)協(xié)議,同時也是事實上的工業(yè)標(biāo)準(zhǔn)。Linux 的網(wǎng)絡(luò)實現(xiàn)支持 BSD 套接字,支持全部的TCP/IP協(xié)議。

Linux內(nèi)核的網(wǎng)絡(luò)部分由BSD套接字、網(wǎng)絡(luò)協(xié)議層和網(wǎng)絡(luò)設(shè)備驅(qū)動程序組成。網(wǎng)絡(luò)設(shè)備驅(qū)動程序負(fù)責(zé)與硬件設(shè)備通訊,每一種可能的硬件設(shè)備都有相應(yīng)的設(shè)備驅(qū)動程序。

二、Linux shell

2.1什么是 shell

Shell 是系統(tǒng)的用戶界面,提供了用戶和內(nèi)核進(jìn)行交互操作的一種接口。同時,Shell 也是一個命令解釋器,它解釋由用戶輸入的命令并且把它們送到內(nèi)核。不僅如此,Shell 有自己的編程語言用于對命令的編輯,它允許用戶編寫由 shell 命令組成的程序。

通常在圖形界面中對實際體驗帶來差異的不是不同發(fā)行版的各種終端模擬器,而是這個 Shell(殼)。有殼就有核,這里的核就是指 UNIX/Linux 內(nèi)核,Shell 是指“提供給使用者使用界面”的軟件(命令解析器),類似于 DOS 下的 command(命令行)和后來的 cmd.exe 。

UNIX/Linux 操作系統(tǒng)下的 Shell 既是用戶交互的界面,也是控制系統(tǒng)的腳本語言。當(dāng)然這一點(diǎn)有別于 Windows 下的命令行,雖然該命令行也提供很簡單的控制語句。在 Windows 操作系統(tǒng)下,有些用戶從來都不會直接使用 Shell。然而在 UNIX 系列操作系統(tǒng)下,Shell 仍然是控制系統(tǒng)啟動和其它很多實用工具的腳本解釋程序。

2.2shell 類別

在UNIX/Linux 中比較常見的 Shell:

  • Bourne Again Shell (簡稱 bash)
  • Bourne Shell(簡稱 sh)
  • C-Shell(簡稱 csh)
  • Korn Shell(簡稱 ksh)
  • Z shell(簡稱 zsh)

Ubuntu 終端默認(rèn)使用的是 bash,默認(rèn)的桌面環(huán)境是GNOME 或者 Unity(基于 GNOME),我們的環(huán)境中使用的分別是 zsh 和 xfce;還可以通過 cat /etc/shells 來查看我們主機(jī)上的 shell 類型。

目前主要有下列版本的shell:

  1. Bourne Shell:是貝爾實驗室開發(fā)的。
  2. BASH:是GNU的Bourne Again Shell,是GNU操作系統(tǒng)上默認(rèn)的shell,大部分linux的發(fā)行套件使用的都是這種shell。
  3. Korn Shell:是對Bourne SHell的發(fā)展,在大部分內(nèi)容上與Bourne Shell兼容。
  4. C Shell:是SUN公司Shell的BSD版本。

三、Linux系統(tǒng)文件

3.1文件系統(tǒng)的概念

首先我們來想一個問題,磁盤等存儲設(shè)備上存儲的不過是01100111這樣的字符數(shù)據(jù),但是為什么我們在電腦上打開某盤訪問時看到的卻是整齊的目錄結(jié)構(gòu)呢,一塊磁盤上的數(shù)據(jù)是怎樣被操作系統(tǒng)識別為一棵目錄樹然后被我們讀寫訪問的?這其中就離不開文件系統(tǒng)。

文件系統(tǒng)是用于在存儲設(shè)備或分區(qū)上組織管理文件的方法和數(shù)據(jù)結(jié)構(gòu),每一個系統(tǒng)可讀寫文件的設(shè)備上都包含了一個完整的系統(tǒng)可識別的文件系統(tǒng)用來組織設(shè)備上的文件,比如我們常用的U盤,里面就有一個FAT32、NTFS或者exFAT等其它類型的文件系統(tǒng),再比如我們打開Linux系統(tǒng)中的設(shè)備目錄/dev,其中每一個可讀取的塊設(shè)備上都有一個文件系統(tǒng),正因如此我們才可以把這樣的塊設(shè)備掛載到系統(tǒng)的某個目錄然后訪問其中的文件。另外我們也可以注意到,一個可讀取設(shè)備即使沒有存儲任何文件,它的存儲空間也已經(jīng)被使用了一部分,這部分就是文件系統(tǒng)所占用的空間。

我們常常對一個設(shè)備進(jìn)行格式化操作,這里的格式化就是指采用指定文件系統(tǒng)類型對設(shè)備空間進(jìn)行登記索引并建立相應(yīng)的管理表格的一個過程;在Linux中,正因為有文件系統(tǒng),我們可以把任何設(shè)備一視同仁當(dāng)作一個文件看待,這也是Linux的設(shè)計哲學(xué)之一:一切皆文件。

文件類型

Linux下面的文件類型主要有:

  • 普通文件:C語言元代碼、SHELL腳本、二進(jìn)制的可執(zhí)行文件等。分為純文本和二進(jìn)制。
  • 目錄文件:目錄,存儲文件的唯一地方。
  • 鏈接文件:指向同一個文件或目錄的的文件。
  • 設(shè)備文件:與系統(tǒng)外設(shè)相關(guān)的,通常在/dev下面。分為塊設(shè)備和字符設(shè)備。
  • 管道(FIFO)文件 : 提供進(jìn)程建通信的一種方式
  • 套接字(socket) 文件:該文件類型與網(wǎng)絡(luò)通信有關(guān)可以通過ls –l, file, stat幾個命令來查看文件的類型等相關(guān)信息。

Linux目錄

文件結(jié)構(gòu)是文件存放在磁盤等存貯設(shè)備上的組織方法。主要體現(xiàn)在對文件和目錄的組織上。目錄提供了管理文件的一個方便而有效的途徑。Linux使用標(biāo)準(zhǔn)的目錄結(jié)構(gòu),在安裝的時候,安裝程序就已經(jīng)為用戶創(chuàng)建了文件系統(tǒng)和完整而固定的目錄組成形式,并指定了每個目錄的作用和其中的文件類型。

完整的目錄樹可劃分為小的部分,這些小部分又可以單獨(dú)存放在自己的磁盤或分區(qū)上。這樣,相對穩(wěn)定的部分和經(jīng)常變化的部分可單獨(dú)存放在不同的分區(qū)中,從而方便備份或系統(tǒng)管理。目錄樹的主要部分有 root、/usr、/var、/home 等(圖2) 。這樣的布局可方便在 Linux 計算機(jī)之間共享文件系統(tǒng)的某些部分。

Linux采用的是樹型結(jié)構(gòu)。最上層是根目錄,其他的所有目錄都是從根目錄出發(fā)而生成的。微軟的DOS和windows也是采用樹型結(jié)構(gòu),但是在DOS和 windows中這樣的樹型結(jié)構(gòu)的根是磁盤分區(qū)的盤符,有幾個分區(qū)就有幾個樹型結(jié)構(gòu),他們之間的關(guān)系是并列的。

最頂部的是不同的磁盤(分區(qū)),如:C,D,E,F(xiàn)等。但是在linux中,無論操作系統(tǒng)管理幾個磁盤分區(qū),這樣的目錄樹只有一個。從結(jié)構(gòu)上講,各個磁盤分區(qū)上的樹型目錄不一定是并列的。

3.2虛擬文件系統(tǒng)(VFS)的概念

在Linux中支持多達(dá)數(shù)十套文件系統(tǒng),不同設(shè)備上的文件系統(tǒng)可能都不一樣,那么為什么我們在實際操作時可以不用理會設(shè)備上的文件系統(tǒng)類型,就能用統(tǒng)一的命令對不同設(shè)備上的文件進(jìn)行讀寫呢?這就涉及到在文件系統(tǒng)上層的抽象層,虛擬文件系統(tǒng)。

學(xué)過面向?qū)ο缶秃芎美斫猓摂M文件系統(tǒng)作為抽象層規(guī)定了一個文件系統(tǒng)要實現(xiàn)哪些接口和數(shù)據(jù)結(jié)構(gòu),文件系統(tǒng)研發(fā)人員就依據(jù)這些標(biāo)準(zhǔn)去研發(fā),因此即使不同文件系統(tǒng)內(nèi)部實現(xiàn)各有不同,但是都實現(xiàn)了可供上層虛擬文件系統(tǒng)進(jìn)行統(tǒng)一調(diào)用的接口,用戶不需要關(guān)心各個文件系統(tǒng)內(nèi)部的實現(xiàn)細(xì)節(jié),只要通過統(tǒng)一的系統(tǒng)調(diào)用(比如open()、read()、write())就可以讀取不同文件系統(tǒng)上的文件數(shù)據(jù),從用戶的角度看就好像只有一個文件系統(tǒng)一樣。

3.3Unix文件系統(tǒng)

VFS提供了一個通用的文件系統(tǒng)模型,該模型囊括了任何文件系統(tǒng)的常用功能集和行為,該模型偏重于Unix風(fēng)格的文件系統(tǒng)。Unix文件系統(tǒng)主要有四個抽象概念:文件、目錄項、索引節(jié)點(diǎn)和安裝點(diǎn)。

(1)安裝點(diǎn):當(dāng)我們運(yùn)行一個Linux操作系統(tǒng)時,我們可以發(fā)現(xiàn)整個操作系統(tǒng)看起來就是一棵目錄樹,最頂層的目錄為根目錄"/",所有文件都組織在這個目錄樹中,這個最頂層的文件系統(tǒng)就稱為根文件系統(tǒng),所有已安裝的文件系統(tǒng)都作為根文件系統(tǒng)樹的枝葉出現(xiàn)在系統(tǒng)中,當(dāng)我們新增一個設(shè)備(文件系統(tǒng))時,需要將其掛載到目錄樹中的某個目錄中才能進(jìn)行訪問,這個目錄就稱為安裝點(diǎn)。

(2)文件:文件就是一個有序字節(jié)串,字節(jié)串中第一個字節(jié)就是文件的頭,最后一個字節(jié)就是文件的尾。

(3)目錄項:目錄也是文件,也是用索引節(jié)點(diǎn)唯一標(biāo)識,和普通文件不同的是,普通文件在磁盤里面保存的是文件數(shù)據(jù),而目錄文件在磁盤里面保存子目錄或文件。

目錄項和目錄是一個東西嗎?

雖然名字很相近,但是它們不是一個東西,目錄是個文件,持久化存儲在磁盤,而目錄項是內(nèi)核一個數(shù)據(jù)結(jié)構(gòu),緩存在內(nèi)存。

如果查詢目錄頻繁從磁盤讀,效率會很低,所以內(nèi)核會把已經(jīng)讀過的目錄用目錄項這個數(shù)據(jù)結(jié)構(gòu)緩存在內(nèi)存,下次再次讀到相同的目錄時,只需從內(nèi)存讀就可以,大大提高了文件系統(tǒng)的效率。

(4)索引節(jié)點(diǎn)(inode):Unix文件系統(tǒng)將文件的相關(guān)信息和文件本身這兩個概念加以區(qū)分,例如訪問控制權(quán)限、文件大小、擁有者和創(chuàng)建時間等就屬于文件相關(guān)信息,存儲在一個單獨(dú)的數(shù)據(jù)結(jié)構(gòu)當(dāng)中,該結(jié)構(gòu)稱為索引節(jié)點(diǎn)

3.4文件系統(tǒng)特點(diǎn)

  • 文件系統(tǒng)要有嚴(yán)格的組織形式,使得文件能夠以塊為單位進(jìn)行存儲。
  • 文件系統(tǒng)中也要有索引區(qū),用來方便查找一個文件分成的多個塊都存放在了什么位置。
  • 如果文件系統(tǒng)中有的文件是熱點(diǎn)文件,近期經(jīng)常被讀取和寫入,文件系統(tǒng)應(yīng)該有緩存層。
  • 文件應(yīng)該用文件夾的形式組織起來,方便管理和查詢。
  • Linux內(nèi)核要在自己的內(nèi)存里面維護(hù)一套數(shù)據(jù)結(jié)構(gòu),來保存哪些文件被哪些進(jìn)程打開和使用。

總體來說,文件系統(tǒng)的主要功能梳理如下:

圖片圖片

3.5EXT系列的文件系統(tǒng)的格式

inode與塊的存儲

硬盤分成相同大小的單元,我們稱為塊(Block)。一塊的大小是扇區(qū)大小的整數(shù)倍,默認(rèn)是4K。在格式化的時候,這個值是可以設(shè)定的。

一大塊硬盤被分成了一個個小的塊,用來存放文件的數(shù)據(jù)部分。這樣一來,如果我們像存放一個文件,就不用給他分配一塊連續(xù)的空間了。我們可以分散成一個個小塊進(jìn)行存放。這樣就靈活得多,也比較容易添加、刪除和插入數(shù)據(jù)。

inode就是文件索引的意思,我們每個文件都會對應(yīng)一個inode;一個文件夾就是一個文件,也對應(yīng)一個inode。

inode數(shù)據(jù)結(jié)構(gòu)如下:

struct ext4_inode {
    __le16  i_mode;     /* File mode */
    __le16  i_uid;      /* Low 16 bits of Owner Uid */
    __le32  i_size_lo;  /* Size in bytes */
    __le32  i_atime;    /* Access time */
    __le32  i_ctime;    /* Inode Change time */
    __le32  i_mtime;    /* Modification time */
    __le32  i_dtime;    /* Deletion Time */
    __le16  i_gid;      /* Low 16 bits of Group Id */
    __le16  i_links_count;  /* Links count */
    __le32  i_blocks_lo;    /* Blocks count */
    __le32  i_flags;    /* File flags */
......
    __le32  i_block[EXT4_N_BLOCKS];/* Pointers to blocks */
    __le32  i_generation;   /* File version (for NFS) */
    __le32  i_file_acl_lo;  /* File ACL */
    __le32  i_size_high;
......
};

inode里面有文件的讀寫權(quán)限i_mode,屬于哪個用戶i_uid,哪個組i_gid,大小是多少i_size_io,占用多少個塊i_blocks_io,i_atime是access time,是最近一次訪問文件的時間;i_ctime是change time,是最近一次更改inode的時間;i_mtime是modify time,是最近一次更改文件的時間等。

所有的文件都是保存在i_block里面。具體保存規(guī)則由EXT4_N_BLOCKS決定,EXT4_N_BLOCKS有如下的定義:

#define    EXT4_NDIR_BLOCKS        12
#define    EXT4_IND_BLOCK          EXT4_NDIR_BLOCKS
#define    EXT4_DIND_BLOCK         (EXT4_IND_BLOCK + 1)
#define    EXT4_TIND_BLOCK         (EXT4_DIND_BLOCK + 1)
#define    EXT4_N_BLOCKS           (EXT4_TIND_BLOCK + 1)

在ext2和ext3中,其中前12項直接保存了塊的位置,也就是說,我們可以通過i_block[0-11],直接得到保存文件內(nèi)容的塊。

圖片圖片

但是,如果一個文件比較大,12塊放不下。當(dāng)我們用到i_block[12]的時候,就不能直接放數(shù)據(jù)塊的位置了,要不然i_block很快就會用完了。

那么可以讓i_block[12]指向一個塊,這個塊里面不放數(shù)據(jù)塊,而是放數(shù)據(jù)塊的位置,這個塊我們稱為間接塊。如果文件再大一些,i_block[13]會指向一個塊,我們可以用二次間接塊。二次間接塊里面存放了間接塊的位置,間接塊里面存放了數(shù)據(jù)塊的位置,數(shù)據(jù)塊里面存放的是真正的數(shù)據(jù)。如果文件再大點(diǎn),那么i_block[14]同理。這里面有一個非常顯著的問題,對于大文件來講,我們要多次讀取硬盤才能找到相應(yīng)的塊,這樣訪問速度就會比較慢。

為了解決這個問題,ext4做了一定的改變。它引入了一個新的概念,叫作Extents。比方說,一個文件大小為128M,如果使用4k大小的塊進(jìn)行存儲,需要32k個塊。如果按照ext2或者ext3那樣散著放,數(shù)量太大了。但是Extents可以用于存放連續(xù)的塊,也就是說,我們可以把128M放在一個Extents里面。這樣的話,對大文件的讀寫性能提高了,文件碎片也減少了。

Exents是一個樹狀結(jié)構(gòu):

圖片圖片

每個節(jié)點(diǎn)都有一個頭,ext4_extent_header可以用來描述某個節(jié)點(diǎn):

struct ext4_extent_header {
    __le16  eh_magic;   /* probably will support different formats */
    __le16  eh_entries; /* number of valid entries */
    __le16  eh_max;     /* capacity of store in entries */
    __le16  eh_depth;   /* has tree real underlying blocks? */
    __le32  eh_generation;  /* generation of the tree */
};

eh_entries表示這個節(jié)點(diǎn)里面有多少項。這里的項分兩種,如果是葉子節(jié)點(diǎn),這一項會直接指向硬盤上的連續(xù)塊的地址,我們稱為數(shù)據(jù)節(jié)點(diǎn)ext4_extent;如果是分支節(jié)點(diǎn),這一項會指向下一層的分支節(jié)點(diǎn)或者葉子節(jié)點(diǎn),我們稱為索引節(jié)點(diǎn)ext4_extent_idx。這兩種類型的項的大小都是12個byte。

/*
 * This is the extent on-disk structure.
 * It's used at the bottom of the tree.
 */
struct ext4_extent {
    __le32  ee_block;   /* first logical block extent covers */
    __le16  ee_len;     /* number of blocks covered by extent */
    __le16  ee_start_hi;    /* high 16 bits of physical block */
    __le32  ee_start_lo;    /* low 32 bits of physical block */
};
/*
 * This is index on-disk structure.
 * It's used at all the levels except the bottom.
 */
struct ext4_extent_idx {
    __le32  ei_block;   /* index covers logical blocks from 'block' */
    __le32  ei_leaf_lo; /* pointer to the physical block of the next *
                 * level. leaf or next index could be there */
    __le16  ei_leaf_hi; /* high 16 bits of physical block */
    __u16   ei_unused;
};

如果文件不大,inode里面的i_block中,可以放得下一個ext4_extent_header和4項ext4_extent。所以這個時候,eh_depth為0,也即inode里面的就是葉子節(jié)點(diǎn),樹高度為0。

如果文件比較大,4個extent放不下,就要分裂成為一棵樹,eh_depth>0的節(jié)點(diǎn)就是索引節(jié)點(diǎn),其中根節(jié)點(diǎn)深度最大,在inode中。最底層eh_depth=0的是葉子節(jié)點(diǎn)。除了根節(jié)點(diǎn),其他的節(jié)點(diǎn)都保存在一個塊4k里面,4k扣除ext4_extent_header的12個byte,剩下的能夠放340項,每個extent最大能表示128MB的數(shù)據(jù),340個extent會使你的表示的文件達(dá)到42.5GB。

inode位圖和塊位圖

inode的位圖大小為4k,每一位對應(yīng)一個inode。如果是1,表示這個inode已經(jīng)被用了;如果是0,則表示沒被用。block的位圖同理。

在Linux操作系統(tǒng)里面,想要創(chuàng)建一個新文件,會調(diào)用open函數(shù),并且參數(shù)會有O_CREAT。這表示當(dāng)文件找不到的時候,我們就需要創(chuàng)建一個。那么open函數(shù)的調(diào)用過程大致是:要打開一個文件,先要根據(jù)路徑找到文件夾。如果發(fā)現(xiàn)文件夾下面沒有這個文件,同時又設(shè)置了O_CREAT,就說明我們要在這個文件夾下面創(chuàng)建一個文件。

創(chuàng)建一個文件,那么就需要創(chuàng)建一個inode,那么就會從文件系統(tǒng)里面讀取inode位圖,然后找到下一個為0的inode,就是空閑的inode。對于block位圖,在寫入文件的時候,也會有這個過程。

3.6文件系統(tǒng)的格式

數(shù)據(jù)塊的位圖是放在一個塊里面的,共4k。這個時候就需要用到塊組,數(shù)據(jù)結(jié)構(gòu)為ext4_group_desc,這里面對于一個塊組里的inode位圖bg_inode_bitmap_lo、塊位圖bg_block_bitmap_lo、inode列表bg_inode_table_lo,都有相應(yīng)的成員變量。、

這樣一個個塊組,就基本構(gòu)成了我們整個文件系統(tǒng)的結(jié)構(gòu)。因為塊組有多個,塊組描述符也同樣組成一個列表,我們把這些稱為塊組描述符表。

我們還需要有一個數(shù)據(jù)結(jié)構(gòu),對整個文件系統(tǒng)的情況進(jìn)行描述,這個就是超級塊ext4_super_block。里面有整個文件系統(tǒng)一共有多少inode,s_inodes_count;一共有多少塊,s_blocks_count_lo,每個塊組有多少inode,s_inodes_per_group,每個塊組有多少塊,s_blocks_per_group等。這些都是這類的全局信息。

最終,整個文件系統(tǒng)格式就是下面這個樣子,如下圖所示:

圖片圖片

默認(rèn)情況下,超級塊和塊組描述符表都有副本保存在每一個塊組里面。防止這些數(shù)據(jù)丟失了,導(dǎo)致整個文件系統(tǒng)都打不開了。由于如果每個塊組里面都保存一份完整的塊組描述符表,一方面很浪費(fèi)空間;另一個方面,由于一個塊組最大128M,而塊組描述符表里面有多少項,這就限制了有多少個塊組,128M * 塊組的總數(shù)目是整個文件系統(tǒng)的大小,就被限制住了。

因此引入Meta Block Groups特性,首先,塊組描述符表不會保存所有塊組的描述符了,而是將塊組分成多個組,我們稱為元塊組(Meta Block Group)。每個元塊組里面的塊組描述符表僅僅包括自己的,一個元塊組包含64個塊組,這樣一個元塊組中的塊組描述符表最多64項。

我們假設(shè)一共有256個塊組,原來是一個整的塊組描述符表,里面有256項,要備份就全備份,現(xiàn)在分成4個元塊組,每個元塊組里面的塊組描述符表就只有64項了,這就小多了,而且四個元塊組自己備份自己的。根據(jù)圖中,每一個元塊組包含64個塊組,塊組描述符表也是64項,備份三份,在元塊組的第一個,第二個和最后一個塊組的開始處。

如果開啟了sparse_super特性,超級塊和塊組描述符表的副本只會保存在塊組索引為0、3、5、7的整數(shù)冪里。所以上圖的超級塊只在索引為0、3、5、7等的整數(shù)冪里。

圖片圖片

根據(jù)圖中,每一個元塊組包含64個塊組,塊組描述符表也是64項,備份三份,在元塊組的第一個,第二個和最后一個塊組的開始處。

如果開啟了sparse_super特性,超級塊和塊組描述符表的副本只會保存在塊組索引為0、3、5、7的整數(shù)冪里。所以上圖的超級塊只在索引為0、3、5、7等的整數(shù)冪里。

四、目錄的儲存格式

其實目錄本身也是個文件,也有inode。inode里面也是指向一些塊。和普通文件不同的是,普通文件的塊里面保存的是文件數(shù)據(jù),而目錄文件的塊里面保存的是目錄里面一項一項的文件信息。這些信息我們稱為ext4_dir_entry。

在目錄文件的塊中,最簡單的保存格式是列表,每一項都會保存這個目錄的下一級的文件的文件名和對應(yīng)的inode,通過這個inode,就能找到真正的文件。第一項是“.”,表示當(dāng)前目錄,第二項是“…”,表示上一級目錄,接下來就是一項一項的文件名和inode。

如果在inode中設(shè)置EXT4_INDEX_FL標(biāo)志,那么就表示根據(jù)索引查找文件。索引項會維護(hù)一個文件名的哈希值和數(shù)據(jù)塊的一個映射關(guān)系。

如果我們要查找一個目錄下面的文件名,可以通過名稱取哈希。如果哈希能夠匹配上,就說明這個文件的信息在相應(yīng)的塊里面。然后打開這個塊,如果里面不再是索引,而是索引樹的葉子節(jié)點(diǎn)的話,那里面還是ext4_dir_entry的列表,我們只要一項一項找文件名就行。通過索引樹,我們可以將一個目錄下面的N多的文件分散到很多的塊里面,可以很快地進(jìn)行查找。

4.1ext4 文件系統(tǒng)

ext4 文件系統(tǒng)作為 Linux 中常用的文件系統(tǒng)之一,是 ext 文件系統(tǒng)的后續(xù)版本,有著諸多顯著優(yōu)勢。

在性能方面,它相比之前版本有了很大提升,例如支持更快的文件創(chuàng)建、刪除以及文件系統(tǒng)檢查等操作。其采用了 extents(連續(xù)的數(shù)據(jù)塊分配)特性,在處理大文件時效率更高,減少了元數(shù)據(jù)的碎片化,也讓大文件訪問速度得以加快。

對于文件支持大小上,ext4 有著強(qiáng)大的擴(kuò)展性,能夠支持最大達(dá)到 1 EB(1,048,576 TB)的文件系統(tǒng)大小,單個文件最大尺寸可達(dá) 16 TB,這相比于 ext3 等之前版本有了極大的擴(kuò)充,滿足了對大容量文件存儲的需求。

穩(wěn)定性上,ext4 保留了 EXT3 的日志功能,還增加了如延遲分配日志、多塊分配日志等更多的日志類型,以此確保了數(shù)據(jù)的一致性和完整性,即便遇到如斷電、系統(tǒng)崩潰等異常情況,也能夠借助日志功能快速恢復(fù)文件系統(tǒng)。

而且,ext4 還具備向下兼容性,可以兼容 ext2 和 ext3,如果磁盤之前是用 Ext3 格式化的,用戶能夠在不損失數(shù)據(jù)的情況下升級到 Ext4 文件系統(tǒng),極大方便了老用戶的升級使用,避免了數(shù)據(jù)遷移帶來的風(fēng)險。

在擴(kuò)展性方面,它突破了 ext3 的 32,000 子目錄限制,支持無限數(shù)量的子目錄,為文件和目錄管理提供了更廣闊的空間。同時,它還增加了更多的文件系統(tǒng)級別的加密和壓縮功能,進(jìn)一步提高數(shù)據(jù)的安全性和存儲效率,并且支持在線文件系統(tǒng)檢查和在線文件系統(tǒng)碎片整理,可提高文件系統(tǒng)的可用性和性能。

ext4 文件系統(tǒng)憑借這些優(yōu)勢,在眾多應(yīng)用場景中被廣泛使用,特別適合對文件系統(tǒng)的性能、可靠性和擴(kuò)展性要求較高的場景,像數(shù)據(jù)庫服務(wù)器、郵件服務(wù)器、文件共享服務(wù)器等,在金融、醫(yī)療、政府等對數(shù)據(jù)安全和存儲效率要求嚴(yán)格的領(lǐng)域也表現(xiàn)出色,也適用于云計算、虛擬化等需要在線文件系統(tǒng)檢查和碎片整理的環(huán)境。

4.2Btrfs 文件系統(tǒng)

Btrfs 文件系統(tǒng)是 Linux 系統(tǒng)中較為先進(jìn)的文件系統(tǒng),具備很多強(qiáng)大且實用的特性。

數(shù)據(jù)壓縮是其一大亮點(diǎn),它支持透明的文件系統(tǒng)壓縮,壓縮后的文件對用戶來說就如同常規(guī)的未壓縮文件一樣,只是它們在硬盤上是以壓縮狀態(tài)存儲的。并且它提供了多個壓縮算法的選擇,例如 zstd、lz、zlib 等,用戶可按需選用,這種壓縮特性能夠有效節(jié)省存儲空間,尤其在存儲空間緊張時作用明顯。

寫時復(fù)制(Copy-on-Write,簡稱 CoW)是 Btrfs 的核心特性之一,采用這種策略,在對文件進(jìn)行復(fù)制、更新及替換操作時,并非傳統(tǒng)的 “就地” 更新,而是通過復(fù)制、更新指針的方式來完成,這有助于保證文件系統(tǒng)的一致性,特別是在面對系統(tǒng)出現(xiàn)不可預(yù)料的硬件故障等情況時,能夠很好地避免數(shù)據(jù)出現(xiàn)問題。

Btrfs 還支持快照功能,用戶可以方便地創(chuàng)建文件系統(tǒng)或者單個文件的快照,便于進(jìn)行備份或者系統(tǒng)恢復(fù)等操作,這在開發(fā)、測試環(huán)境中非常實用,比如可以快速創(chuàng)建某個項目文件的快照,方便在出現(xiàn)問題時回滾到之前的狀態(tài)。

此外,它還支持 RAID,能夠聯(lián)機(jī)添加、移除以及修改設(shè)備,方便管理多個物理設(shè)備,使得傳統(tǒng)的卷管理軟件變得多余,同時可以實現(xiàn)存儲池的靈活管理,能夠在線添加或移除磁盤,動態(tài)調(diào)整容量,滿足不同存儲規(guī)模的需求。

從參數(shù)方面來看,Btrfs 文件系統(tǒng)支持最大文件系統(tǒng)大小為 16 EB(18,446,744,073,709,551,616 字節(jié)),最大文件大小同樣為 16 EB,為處理海量數(shù)據(jù)提供了可能。

4.3XFS 文件系統(tǒng)

XFS 作為高性能日志文件系統(tǒng),有著諸多獨(dú)特的特性使其在眾多文件系統(tǒng)中脫穎而出。

它具有強(qiáng)大的處理大容量文件系統(tǒng)和大文件的能力,最初由 SGI 公司開發(fā),如今已成為 Linux 內(nèi)核的一部分,最大支持 16 EB(艾字節(jié))的文件系統(tǒng)和最大 8 EB 的單個文件,特別適合大規(guī)模數(shù)據(jù)存儲的場景,像大規(guī)模數(shù)據(jù)庫、文件服務(wù)器等應(yīng)用場景中,XFS 都能很好地應(yīng)對大量數(shù)據(jù)的管理需求。

其日志功能十分出色,通過記錄文件系統(tǒng)的操作,在系統(tǒng)異常重啟后,可以依據(jù)日志快速恢復(fù),提高了文件系統(tǒng)的可靠性和穩(wěn)定性,確保數(shù)據(jù)完整性不受太大影響。

動態(tài)增加文件系統(tǒng)大小這一特性也很實用,XFS 支持在線動態(tài)增加文件系統(tǒng)大小,無需卸載文件系統(tǒng),這意味著在存儲需求不斷增長的過程中,能夠方便地對文件系統(tǒng)進(jìn)行擴(kuò)容,而不會影響到正在進(jìn)行的業(yè)務(wù)操作,極大地提高了系統(tǒng)的靈活性和可用性。

另外,XFS 使用延遲分配機(jī)制,在寫入文件時并不會馬上為其分配磁盤空間,而是先寫入頁緩存并做標(biāo)記,待特定條件滿足后再分配磁盤空間并將數(shù)據(jù)寫入磁盤,這種機(jī)制能夠?qū)㈦S機(jī) IO 盡量轉(zhuǎn)換為順序 IO,從而提高文件寫入性能。

五、Linux中的文件緩存

5.1ext4文件系統(tǒng)層

對于ext4文件系統(tǒng)來講,內(nèi)核定義了一個ext4_file_operations

const struct file_operations ext4_file_operations = {
......
    .read_iter  = ext4_file_read_iter,
    .write_iter = ext4_file_write_iter,
......
}

ext4_file_read_iter會調(diào)用generic_file_read_iter,ext4_file_write_iter會調(diào)用__generic_file_write_iter

ssize_t
generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
{
......
    if (iocb->ki_flags & IOCB_DIRECT) {
......
        struct address_space *mapping = file->f_mapping;
......
        retval = mapping->a_ops->direct_IO(iocb, iter);
    }
......
    retval = generic_file_buffered_read(iocb, iter, retval);
}


ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
......
    if (iocb->ki_flags & IOCB_DIRECT) {
......
        written = generic_file_direct_write(iocb, from);
......
    } else {
......
        written = generic_perform_write(file, from, iocb->ki_pos);
......
    }
}

generic_file_read_iter和__generic_file_write_iter有相似的邏輯,就是要區(qū)分是否用緩存。因此,根據(jù)是否使用內(nèi)存做緩存,我們可以把文件的I/O操作分為兩種類型。

第一種類型是緩存I/O。大多數(shù)文件系統(tǒng)的默認(rèn)I/O操作都是緩存I/O。對于讀操作來講,操作系統(tǒng)會先檢查,內(nèi)核的緩沖區(qū)有沒有需要的數(shù)據(jù)。如果已經(jīng)緩存了,那就直接從緩存中返回;否則從磁盤中讀取,然后緩存在操作系統(tǒng)的緩存中。對于寫操作來講,操作系統(tǒng)會先將數(shù)據(jù)從用戶空間復(fù)制到內(nèi)核空間的緩存中。這時對用戶程序來說,寫操作就已經(jīng)完成。至于什么時候再寫到磁盤中由操作系統(tǒng)決定,除非顯式地調(diào)用了sync同步命令。

第二種類型是直接IO,就是應(yīng)用程序直接訪問磁盤數(shù)據(jù),而不經(jīng)過內(nèi)核緩沖區(qū),從而減少了在內(nèi)核緩存和用戶程序之間數(shù)據(jù)復(fù)制。

如果在寫的邏輯__generic_file_write_iter里面,發(fā)現(xiàn)設(shè)置了IOCB_DIRECT,則調(diào)用generic_file_direct_write,里面同樣會調(diào)用address_space的direct_IO的函數(shù),將數(shù)據(jù)直接寫入硬盤。

帶緩存的寫入操作

我們先來看帶緩存寫入的函數(shù)generic_perform_write。

ssize_t generic_perform_write(struct file *file,
                struct iov_iter *i, loff_t pos)
{
    struct address_space *mapping = file->f_mapping;
    const struct address_space_operations *a_ops = mapping->a_ops;
    do {
        struct page *page;
        unsigned long offset;   /* Offset into pagecache page */
        unsigned long bytes;    /* Bytes to write to page */
        status = a_ops->write_begin(file, mapping, pos, bytes, flags,
                        &page, &fsdata);
        copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes);
        flush_dcache_page(page);
        status = a_ops->write_end(file, mapping, pos, bytes, copied,
                        page, fsdata);
        pos += copied;
        written += copied;


        balance_dirty_pages_ratelimited(mapping);
    } while (iov_iter_count(i));
}

循環(huán)中主要做了這幾件事:

  • 對于每一頁,先調(diào)用address_space的write_begin做一些準(zhǔn)備;
  • 調(diào)用iov_iter_copy_from_user_atomic,將寫入的內(nèi)容從用戶態(tài)拷貝到內(nèi)核態(tài)的頁中;
  • 調(diào)用address_space的write_end完成寫操作;
  • 調(diào)用balance_dirty_pages_ratelimited,看臟頁是否太多,需要寫回硬盤。所謂臟頁,就是寫入到緩存,但是還沒有寫入到硬盤的頁面。

對于第一步,調(diào)用的是ext4_write_begin來說,主要做兩件事:

第一做日志相關(guān)的工作

ext4是一種日志文件系統(tǒng),是為了防止突然斷電的時候的數(shù)據(jù)丟失,引入了日志(Journal)模式。日志文件系統(tǒng)比非日志文件系統(tǒng)多了一個Journal區(qū)域。文件在ext4中分兩部分存儲,一部分是文件的元數(shù)據(jù),另一部分是數(shù)據(jù)。元數(shù)據(jù)和數(shù)據(jù)的操作日志Journal也是分開管理的。你可以在掛載ext4的時候,選擇Journal模式。這種模式在將數(shù)據(jù)寫入文件系統(tǒng)前,必須等待元數(shù)據(jù)和數(shù)據(jù)的日志已經(jīng)落盤才能發(fā)揮作用。這樣性能比較差,但是最安全。

另一種模式是order模式。這個模式不記錄數(shù)據(jù)的日志,只記錄元數(shù)據(jù)的日志,但是在寫元數(shù)據(jù)的日志前,必須先確保數(shù)據(jù)已經(jīng)落盤。這個折中,是默認(rèn)模式。

還有一種模式是writeback,不記錄數(shù)據(jù)的日志,僅記錄元數(shù)據(jù)的日志,并且不保證數(shù)據(jù)比元數(shù)據(jù)先落盤。這個性能最好,但是最不安全。

第二調(diào)用grab_cache_page_write_begin來,得到應(yīng)該寫入的緩存頁。

struct page *grab_cache_page_write_begin(struct address_space *mapping,
                    pgoff_t index, unsigned flags)
{
    struct page *page;
    int fgp_flags = FGP_LOCK|FGP_WRITE|FGP_CREAT;
    page = pagecache_get_page(mapping, index, fgp_flags,
            mapping_gfp_mask(mapping));
    if (page)
        wait_for_stable_page(page);
    return page;
}

在內(nèi)核中,緩存以頁為單位放在內(nèi)存里面,每一個打開的文件都有一個struct file結(jié)構(gòu),每個struct file結(jié)構(gòu)都有一個struct address_space用于關(guān)聯(lián)文件和內(nèi)存,就是在這個結(jié)構(gòu)里面,有一棵樹,用于保存所有與這個文件相關(guān)的的緩存頁。

對于第二步,調(diào)用iov_iter_copy_from_user_atomic。先將分配好的頁面調(diào)用kmap_atomic映射到內(nèi)核里面的一個虛擬地址,然后將用戶態(tài)的數(shù)據(jù)拷貝到內(nèi)核態(tài)的頁面的虛擬地址中,調(diào)用kunmap_atomic把內(nèi)核里面的映射刪除。

size_t iov_iter_copy_from_user_atomic(struct page *page,
        struct iov_iter *i, unsigned long offset, size_t bytes)
{
    char *kaddr = kmap_atomic(page), *p = kaddr + offset;
    iterate_all_kinds(i, bytes, v,
        copyin((p += v.iov_len) - v.iov_len, v.iov_base, v.iov_len),
        memcpy_from_page((p += v.bv_len) - v.bv_len, v.bv_page,
                 v.bv_offset, v.bv_len),
        memcpy((p += v.iov_len) - v.iov_len, v.iov_base, v.iov_len)
    )
    kunmap_atomic(kaddr);
    return bytes;
}

第三步中,調(diào)用ext4_write_end完成寫入。這里面會調(diào)用ext4_journal_stop完成日志的寫入,會調(diào)用block_write_end->__block_commit_write->mark_buffer_dirty,將修改過的緩存標(biāo)記為臟頁。可以看出,其實所謂的完成寫入,并沒有真正寫入硬盤,僅僅是寫入緩存后,標(biāo)記為臟頁。

第四步,調(diào)用balance_dirty_pages_ratelimited,是回寫臟頁

/**
 * balance_dirty_pages_ratelimited - balance dirty memory state
 * @mapping: address_space which was dirtied
 *
 * Processes which are dirtying memory should call in here once for each page
 * which was newly dirtied.  The function will periodically check the system's
 * dirty state and will initiate writeback if needed.
  */
void balance_dirty_pages_ratelimited(struct address_space *mapping)
{
    struct inode *inode = mapping->host;
    struct backing_dev_info *bdi = inode_to_bdi(inode);
    struct bdi_writeback *wb = NULL;
    int ratelimit;
......
    if (unlikely(current->nr_dirtied >= ratelimit))
        balance_dirty_pages(mapping, wb, current->nr_dirtied);
......
}

在balance_dirty_pages_ratelimited里面,發(fā)現(xiàn)臟頁的數(shù)目超過了規(guī)定的數(shù)目,就調(diào)用balance_dirty_pages->wb_start_background_writeback,啟動一個背后線程開始回寫。

另外還有幾種場景也會觸發(fā)回寫:

  • 用戶主動調(diào)用sync,將緩存刷到硬盤上去,最終會調(diào)用wakeup_flusher_threads,同步臟頁;
  • 當(dāng)內(nèi)存十分緊張,以至于無法分配頁面的時候,會調(diào)用free_more_memory,最終會調(diào)用wakeup_flusher_threads,釋放臟頁;
  • 臟頁已經(jīng)更新了較長時間,時間上超過了設(shè)定時間,需要及時回寫,保持內(nèi)存和磁盤上數(shù)據(jù)一致性。

5.2帶緩存的讀操作

看帶緩存的讀,對應(yīng)的是函數(shù)generic_file_buffered_read。

static ssize_t generic_file_buffered_read(struct kiocb *iocb,
        struct iov_iter *iter, ssize_t written)
{
    struct file *filp = iocb->ki_filp;
    struct address_space *mapping = filp->f_mapping;
    struct inode *inode = mapping->host;
    for (;;) {
        struct page *page;
        pgoff_t end_index;
        loff_t isize;
        page = find_get_page(mapping, index);
        if (!page) {
            if (iocb->ki_flags & IOCB_NOWAIT)
                goto would_block;
            page_cache_sync_readahead(mapping,
                    ra, filp,
                    index, last_index - index);
            page = find_get_page(mapping, index);
            if (unlikely(page == NULL))
                goto no_cached_page;
        }
        if (PageReadahead(page)) {
            page_cache_async_readahead(mapping,
                    ra, filp, page,
                    index, last_index - index);
        }
        /*
         * Ok, we have the page, and it's up-to-date, so
         * now we can copy it to user space...
         */
        ret = copy_page_to_iter(page, offset, nr, iter);
    }
}

在generic_file_buffered_read函數(shù)中,我們需要先找到page cache里面是否有緩存頁。如果沒有找到,不但讀取這一頁,還要進(jìn)行預(yù)讀,這需要在page_cache_sync_readahead函數(shù)中實現(xiàn)。預(yù)讀完了以后,再試一把查找緩存頁。

如果第一次找緩存頁就找到了,我們還是要判斷,是不是應(yīng)該繼續(xù)預(yù)讀;如果需要,就調(diào)用page_cache_async_readahead發(fā)起一個異步預(yù)讀。

最后,copy_page_to_iter會將內(nèi)容從內(nèi)核緩存頁拷貝到用戶內(nèi)存空間。

六、Linux應(yīng)用

標(biāo)準(zhǔn)的Linux系統(tǒng)一般都有一套都有稱為應(yīng)用程序的程序集,它包括文本編輯器、編程語言、X Window、辦公套件、Internet工具和數(shù)據(jù)庫等。

七、Linux內(nèi)核參數(shù)優(yōu)化

內(nèi)核參數(shù)是用戶和系統(tǒng)內(nèi)核之間交互的一個接口,通過這個接口,用戶可以在系統(tǒng)運(yùn)行的同時動態(tài)更新內(nèi)核配置,而這些內(nèi)核參數(shù)是通過Linux Proc文件系統(tǒng)存在的。因此,可以通過調(diào)整Proc文件系統(tǒng)達(dá)到優(yōu)化Linux性能的目的。

責(zé)任編輯:武曉燕 來源: 深度Linux
相關(guān)推薦

2020-07-27 10:40:35

C++11語言代碼

2023-09-08 13:46:12

ArrayList數(shù)據(jù)存儲容器

2020-10-22 12:30:33

MySQL

2023-09-27 09:00:02

SpringBoot并發(fā)編程

2020-09-16 10:50:16

C++14語言代碼

2009-12-23 16:35:12

Linux系統(tǒng)光驅(qū)軟

2011-01-06 14:03:18

2021-05-18 09:03:16

Gomapslice

2024-01-24 11:59:44

Django自定義字段Python

2021-12-14 08:51:23

Linux 中斷子系統(tǒng)Linux 系統(tǒng)

2016-10-31 19:22:24

JavaScript語法

2020-11-06 00:50:16

JavaClassLoaderJVM

2010-08-18 10:52:46

Linux筆試

2011-01-13 14:10:30

Linux文件系統(tǒng)

2010-04-29 10:11:17

Unix系統(tǒng)

2010-04-13 13:31:31

Unix文件

2010-05-05 17:46:32

Unix文件系統(tǒng)

2020-02-18 08:01:55

在家辦公Kakfa知識點(diǎn)大全

2020-07-22 14:53:06

Linux系統(tǒng)虛擬文件

2021-04-12 05:44:44

Linux文件系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

2020欧美日韩在线视频| 亚洲精品美女在线| 国产欧美久久久久| 婷婷久久久久久| 日韩电影在线一区二区三区| 精品国产自在精品国产浪潮| 特黄特色免费视频| 在线看片国产福利你懂的| 国产三级欧美三级| 亚洲最大av网| 亚洲av无码精品一区二区| 偷拍欧美精品| 精品一区二区电影| 人人爽人人爽av| 9i看片成人免费高清| 亚洲欧洲另类国产综合| 蜜桃在线一区二区三区精品| 国产熟女精品视频| 天堂在线一区二区| 欧美精品videos另类日本| 中国女人特级毛片| 黄色网一区二区| 欧美日本国产视频| 日本中文字幕片| 久久av色综合| 亚洲天堂成人在线观看| 欧美在线视频一区二区三区| 性一交一乱一精一晶| 青青草97国产精品免费观看 | 欧美一二三区在线观看| 黄色三级视频片| 国产h片在线观看| 一区2区3区在线看| 椎名由奈jux491在线播放| 日本亚洲欧美| 成人午夜免费视频| 91在线看网站| 国产模特av私拍大尺度| 男女性色大片免费观看一区二区| 国产91精品久久久久| 日本免费在线播放| 亚洲v天堂v手机在线| 欧美二区三区的天堂| 在线观看高清免费视频| 三上悠亚国产精品一区二区三区| 精品成人在线视频| 天堂8在线天堂资源bt| 国产一二三区在线观看| 中文字幕亚洲区| 亚洲春色在线视频| 午夜小视频在线| 欧美激情综合网| 日韩理论片在线观看| 美州a亚洲一视本频v色道| 91老司机福利 在线| 久久国产精品一区二区三区四区| 免费看av毛片| gogogo免费视频观看亚洲一| 国产一区免费在线观看| 亚洲色欧美另类| av高清不卡在线| 欧美二区三区| 成年人在线观看网站| 国产午夜精品一区二区| 日本高清久久一区二区三区| 国产精品免费观看| 国产精品你懂的在线| 永久域名在线精品| 香蕉久久aⅴ一区二区三区| 亚洲综合激情网| 青娱乐自拍偷拍| 亚洲十八**毛片| 欧美在线看片a免费观看| 午夜欧美福利视频| 国产精品xnxxcom| 精品久久久久久无| 日本一区二区三区网站| 成人无号精品一区二区三区| www.亚洲成人| 国产在线精品观看| 美女诱惑一区| 91香蕉亚洲精品| 免费观看国产精品| 国产女同互慰高潮91漫画| 一区二区三区四区视频在线观看| 在线欧美三级| 欧美日韩亚洲天堂| 一级黄色片国产| 国产成人精品亚洲线观看| 日韩精品免费在线播放| 一本色道久久88| 狠色狠色综合久久| 国产精品69av| 亚洲第一色视频| 久久久久久免费毛片精品| 一区在线电影| 日韩影院在线| 日韩一区二区三区免费看| 欧美精品欧美极品欧美激情| 日韩欧美视频| 97香蕉超级碰碰久久免费的优势| 在线免费观看av片| 99re视频这里只有精品| 超碰成人在线免费观看| 亚洲精品永久免费视频| 日韩欧美三级在线| 欧美人妻一区二区三区| 99视频一区| 91成人免费观看| 国产精品一二三区视频| 午夜精品视频在线观看| 在线一区二区不卡| 狠狠操综合网| 国内伊人久久久久久网站视频| 在线观看国产区| 成人激情免费网站| 国产又粗又爽又黄的视频| 日产精品一区| 亚洲黄色在线观看| 久久高清内射无套| 日韩av在线发布| 国产日韩在线一区二区三区| 黄网站免费在线观看| 在线观看亚洲一区| 中文字幕精品视频在线| 午夜精品av| 国产一区二区色| 久久免费看视频| 婷婷成人综合网| 亚洲一级Av无码毛片久久精品| 天堂美国久久| 国产精品午夜国产小视频| 五月婷婷在线观看视频| 一个色在线综合| 国产高清av片| 欧美成人自拍| 国产女精品视频网站免费| 美国一级片在线免费观看视频| 亚洲国产一区二区三区| 韩国三级丰满少妇高潮| 婷婷综合伊人| 92国产精品视频| 激情视频在线观看| 欧美一区二区三区啪啪| 日日噜噜夜夜狠狠久久波多野| 另类专区欧美蜜桃臀第一页| 亚洲日本欧美在线| 99久久久国产精品免费调教网站| 亚洲人午夜精品免费| aaa在线视频| 国产日韩欧美一区二区三区乱码| 手机看片福利盒子久久| 久久久综合色| 成人精品福利视频| www在线观看播放免费视频日本| 欧美乱妇15p| 日本黄色免费片| 日韩高清在线电影| 亚洲一区二区三区免费观看| 在线日韩三级| 欧美精品在线极品| 日韩有码第一页| 色婷婷一区二区| 国产综合精品久久久久成人av| 麻豆精品视频在线观看视频| 一区精品在线| 黄色美女网站在线观看| 国产青青草在线| 成人中文视频| 国产精品成久久久久三级| 国产在线视频福利| 欧美日韩不卡一区二区| 欧美国产日韩在线观看成人| 国产成人亚洲综合a∨婷婷| www.在线观看av| 亚洲人成网www| 91精品国产自产在线| 亚洲夜夜综合| 日韩精品免费在线| 一级黄色片在线看| 亚洲一区二区三区中文字幕| 爱爱免费小视频| 美腿丝袜一区二区三区| 国产一级大片免费看| 啪啪国产精品| 国产一区视频在线播放| 久操av在线| 在线播放日韩av| 亚洲AV无码成人片在线观看| 精品美女久久久久久免费| 青青草自拍偷拍| 成人午夜在线视频| 国产一级不卡毛片| 91精品二区| 欧美一区2区三区4区公司二百| 色婷婷成人网| 538国产精品一区二区在线| 三区四区电影在线观看| 亚洲福利视频专区| 国产美女明星三级做爰| 狠狠躁夜夜躁人人躁婷婷91 | 欧美日韩国产二区| 国内av一区二区三区| 精品免费日韩av| 国产主播第一页| 亚洲成在线观看| 永久免费未视频| 国产欧美日韩在线看| 久久久午夜精品福利内容| 国产一区二区美女| 北条麻妃视频在线| 国产亚洲在线观看| 波多野结衣与黑人| 亚洲va在线| 日韩电影大全在线观看| 久久99精品国产自在现线| 91久久久久久久久久| 亚洲va中文在线播放免费| 欧美成人四级hd版| 日韩黄色影院| 在线观看中文字幕亚洲| 亚洲色偷精品一区二区三区| 日韩精品一区二区三区在线| 一级特黄录像免费看| 在线免费不卡电影| 久久青青草原亚洲av无码麻豆 | www.毛片.com| 亚洲午夜精品一区二区三区他趣| 日韩在线视频免费看| 久久精品视频免费观看| 中国黄色片视频| 国模娜娜一区二区三区| 国产一级做a爰片久久| 亚洲免费大片| 成人在线观看你懂的| 欧美日韩少妇| 老司机午夜免费福利视频| 小小影院久久| 992tv成人免费观看| 国产精品麻豆久久| 国产又大又长又粗又黄| 大色综合视频网站在线播放| 日本精品一区二区三区高清 久久 日本精品一区二区三区不卡无字幕 | 国产情侣一区在线| 91久久综合亚洲鲁鲁五月天| 国产a亚洲精品| 国产欧美日韩高清| 欧美亚洲人成在线| 成人乱色短篇合集| 欧美成人aaa| 91在线观看免费| 1313精品午夜理伦电影| av噜噜色噜噜久久| 999国产精品一区| 国产一区二区视频在线免费观看 | 日本少妇bbwbbw精品| 亚洲福利视频三区| 亚洲免费黄色网址| 在线精品视频一区二区三四| 一区二区乱子伦在线播放| 欧美日韩国产天堂| 国产精品主播一区二区| 日韩欧美一区二区三区在线| 欧美熟妇另类久久久久久不卡| 亚洲第一天堂av| 女人18毛片一区二区三区| 亚洲精品久久7777777| 国产在线黄色| 日韩中文字幕精品视频| 亚洲91av| 欧美综合第一页| 日韩欧国产精品一区综合无码| 1卡2卡3卡精品视频| 美日韩黄色大片| 午夜精品电影在线观看| 综合精品久久| 久久精品一区二| 精品一区二区av| 好吊色视频一区二区三区| 久久蜜桃av一区精品变态类天堂 | 亚洲电影在线免费观看| 国产日产精品一区二区三区| 欧美三级电影网站| 国产91麻豆视频| 一区二区三区亚洲| 暖暖在线中文免费日本| 国产精品91在线观看| 欧美午夜在线播放| 欧美大香线蕉线伊人久久国产精品| 91一区在线| avav在线看| 国产精品一区二区久激情瑜伽| 亚洲激情视频小说| 亚洲制服丝袜av| 中文字幕人妻精品一区| 精品处破学生在线二十三| 成年人视频网站在线| 欧美国产精品人人做人人爱| 日本在线视频一区二区| 国产一区二区三区四区hd| 欧美激情电影| 国产成人无码一二三区视频| 国产成人av电影在线播放| 色欲AV无码精品一区二区久久| 亚洲国产另类av| 99久久精品国产色欲| 亚洲性猛交xxxxwww| 爱看av在线| 亚洲专区在线视频| 波多野结衣在线观看一区二区三区| 97在线国产视频| 国产乱理伦片在线观看夜一区| 91精品国自产在线| 欧美性开放视频| 欧美一级一区二区三区| xxxx性欧美| 亚洲电影有码| 欧美日韩精品免费在线观看视频| 欧美精品福利| 亚洲免费成人在线视频| 国产蜜臀97一区二区三区| 亚洲天堂一区在线观看| 精品日韩一区二区三区| 91精选在线| 91网站在线看| 久久亚洲在线| 日韩爱爱小视频| 国产欧美一区二区精品婷婷| 久久久久久久久黄色| 亚洲国产日韩欧美综合久久| 丝袜在线视频| 亚洲一区精品电影| 91tv精品福利国产在线观看| 亚洲最大成人在线观看| 国产清纯白嫩初高生在线观看91| 国产精品久久久久久久久久久久久久久久久 | www.日本xxxx| 国产亚洲1区2区3区| av网站中文字幕| 亚洲女人被黑人巨大进入| 天堂av在线网| 免费成人深夜夜行视频| 亚洲伊人观看| theav精尽人亡av| 丰满岳妇乱一区二区三区| 人妻精品无码一区二区| 97在线视频免费看| 亚洲最好看的视频| 国产精品天天av精麻传媒| 国产日韩欧美精品电影三级在线| 亚洲精品一区二三区| 在线亚洲午夜片av大片| 国产美女久久| 欧美性受黑人性爽| 国产jizzjizz一区二区| 日本一区二区三区免费视频| 国产视频精品va久久久久久| 播放一区二区| 国产精品av免费| 丁香五精品蜜臀久久久久99网站 | 精品国产免费久久久久久尖叫| 99在线热播精品免费99热| 在线免费观看日韩av| 欧美视频在线一区| www.久久ai| 国产一区免费在线观看| 日韩成人一级大片| 日韩三级久久久| 亚洲福利在线看| 外国电影一区二区| 樱空桃在线播放| 成人精品免费看| 精品久久久久久久久久久久久久久久久久| 在线观看精品国产视频| 国产在线不卡一区二区三区| 久久久亚洲国产精品| 久久精品日产第一区二区三区高清版 | 极品av少妇一区二区| 国产男女猛烈无遮挡a片漫画| 欧美日韩情趣电影| 国内在线视频| 五月天久久狠狠| 成人免费av在线| 中文字幕第315页| 久久久久久国产精品| 国产亚洲一区| 亚洲熟女一区二区三区| 色综合天天综合色综合av | 中文字幕18页| 欧美在线看片a免费观看| 97超碰在线公开在线看免费| 久久久人人爽| 国产经典欧美精品| 久久精品99北条麻妃| 欧美二区在线播放| 欧美一站二站| 国产又粗又长又爽| 日韩欧美激情四射| 日韩欧美精品电影| 成人午夜免费在线|