【Linux】緩沖區和文件系統

一、FILE結構1、fd

file是在c中封裝起來的一個結構體,那我們訪問文件的時候都是通過fd訪問的,自然在file中是封裝了fd的,file結構體中,int _file存放的就是fd,其他的成員基本都是與緩沖區有關的

【Linux】緩沖區和文件系統

2、緩沖區(一)有換行有return全部打印

看下面一段代碼:

【Linux】緩沖區和文件系統
【Linux】緩沖區和文件系統

(二)無換行無return的C接口打印

很顯然的,我們打印出了所有我們需要的內容,我們再看下一段

【Linux】緩沖區和文件系統
【Linux】緩沖區和文件系統

理想狀態下我們應該是打印出結果后然后進行while一直循環,實際上是一只不會打印,這是為什么呢?是的,待在緩沖區里

首先我們要知道,緩沖區的大概位置,我們上面貼了一張FILE結構體的結構圖,我們可以很清楚地看到緩沖區是FILE的成員指針指向的一塊位置,也就是說緩沖區一定在用戶空間而不是內核空間

【Linux】緩沖區和文件系統

(三)無換行無return的系統調用接口打印

我們在調用上面三個函數的時候,都是調用的C接口,自然都待在緩沖區里了,我們再看下一個程序

【Linux】緩沖區和文件系統
【Linux】緩沖區和文件系統

在這個程序中我們直接調用系統調用接口write,所以它不會經過c語言的緩沖區,而是直接打印

(四)有換行無return的C接口打印

我們再來看一組程序

【Linux】緩沖區和文件系統
【Linux】緩沖區和文件系統

這個程序和(二)程序的區別就只有換行,這告訴我們,C語言緩沖區對于顯式器是行緩沖的,C語言標準庫的文件流有三種緩沖模式,分別是全緩沖、行緩沖和無緩沖

全緩沖 _IOFBF :通常用于對磁盤文件的操作,數據會先被存儲在緩沖區中,直到緩沖區被填滿或者調用 fflush 函數、關閉文件(fclose)時,才會將緩沖區中的數據寫入實際的文件,在全緩沖模式下,不會因為遇到換行符而自動刷新緩沖區 行緩沖 _IOLBF :常見于標準輸入、標準輸出等終端設備相關的流,當遇到換行符(n)時,會自動刷新緩沖區,將緩沖區中的數據寫入對應的設備或文件,某些情況下即使沒有換行符,緩沖區滿時也會刷新 無緩沖 _IONBF :標準錯誤輸出通常默認是無緩沖的,確保錯誤信息能夠立即顯示,在無緩沖模式下,數據會立即寫入對應的設備或文件,不會進行緩沖,因此不存在行刷新的概念

(五)無換行有return的C接口打印

【Linux】緩沖區和文件系統
【Linux】緩沖區和文件系統
【Linux】緩沖區和文件系統

進程退出return的時候,也會對緩沖區進行刷新

(六)深入理解緩沖區在用戶空間

【Linux】緩沖區和文件系統
【Linux】緩沖區和文件系統
【Linux】緩沖區和文件系統

我們打印在顯示器上的內容和打印在文件中的內容不一致,只有write打印了一遍,其他是按照順序打印了兩遍,我們當然能看出來這是fork的鍋,接下來我們就深入理解談一談緩沖區

首先我們分析第一張結果圖,因為顯示器是行緩沖的,所以我們C接口的打印放到緩沖區中一行就會被打印到屏幕上一行,三條語句執行完之后緩沖區是空的,然后write再往上寫,所以整個打印出來的順序也是按照代碼中來的

然后我們分析最后一張圖,第一個我們可以肯定的是,打印到文件一定不是行緩沖,那就更不是無緩沖,實際上,由于文件是在存儲硬件當中的,由于我們的效率問題,對于這種存儲類的緩沖條件都是全緩沖,把緩沖區塞滿再寫入存儲硬件中比塞一點寫一點效率高得多,所以前三句C接口調用的打印全部在緩沖區中,然后write將自己打印,然后我們就碰到了fork,創建子進程,父子進程此時共享代碼段和數據段,因為它們都沒有做修改,然后我們就碰到了return 0,前面我們提到:進程結束也是要清空緩沖區的,此時父或子進程某一個先結束(由調度器決定),其中一個進程清空緩沖區的行為會引起另一個進程的寫實拷貝,此時我們就有兩份緩沖區,兩個進程都結束都要清空緩沖區,自然在緩沖區中的內容要打印兩份了(在這里要注意了,不只是子進程修改數據會引起子進程的寫時拷貝,父進程對數據做修改時父進程也要發生寫時拷貝,被寫時拷貝的數據再再發生修改就直接修改了,不發生寫實拷貝)

二、文件系統

文件一般存儲在硬盤當中,我們已經學習了動態的文件,也就是進程打開文件訪問文件的過程,現在我們來學習一下靜態的文件,我們來直接學習一下固態硬盤

1、固態硬盤

固態硬盤是一種基于NAND閃存的存儲單元,我們常用的筆記本上的固態硬盤存儲單元類型一般都是TLC的,三層單元,每個單元存儲3bits,壽命較短成本較低,它通過電荷存儲數據,通過高低電平區分0/1

NAND閃存的寫入操作只能在已擦除的塊上進行,擦除的最小單位就是塊,通常為128KB-4MB,寫入的最小單位是頁,通常為4KB,所以它讀的速度特別快,可以到微秒級,因為需要先擦除塊,寫的速度較慢,只能到毫秒級,每個塊的擦寫次數有限,超過后就會失效,一般TLC的擦鞋上限在500-1500次

這樣的性質會帶來一些不太好的結果,比如我們要寫的內容很小,假設為4KB,那么我們先要擦除高達4MB的塊才能進行寫入,所以我們通過算法,將寫入分散到所有塊,避免某些塊因為多次擦除而失效

固態硬盤控制器中的核心邏輯叫做FTL ( Flash Translation Layer ) Flash翻譯層,負責將文件系統的邏輯地址映射到物理地址,是不是有點像進程地址通過頁表映射到物理地址呢

接下來我們要學習文件系統的邏輯地址LBA,因為我們很清楚FTL映射到物理地址的過程是與頁表映射是相似的,而邏輯地址的組織方式與進程地址可是不同的,雖然是有相似之處的~

2、邏輯地址LBA

LBA 從 0 開始,按照連續的整數順序依次為存儲設備中的每個數據塊編號,存儲設備中的每個數據塊都對應一個唯一的 LBA 值,比如第一個數據塊的 LBA 是 0,第二個是 1,依此類推,我們對應的數據塊有Super Block、Group Descriptor table、Block Bitmap、inode Bitmap、inode Table、Data blocks六個,最理想的情況下它們的LBA按照我上面寫的順序從0到5

我們把一塊固態硬盤,我們筆記本上有一些品牌比如說某L開頭的品牌,在我們購買的時候是默認給你帶1T固態的,一般的品牌就是512G,我們拿到筆記本之后會對電腦進行分區,c盤作為系統盤分到最多的內存,G盤作為游戲盤給到300多G,然后D盤用來學習寫代碼,留個200G,EF盤用來存一些其他的東西,這樣一套流程下來我們就分好盤了,我們說對硬盤做管理當然也是先描述后組織,Block Group就是組織和管理磁盤空間的一種重要結構

【Linux】緩沖區和文件系統

在n個Block Group之前有一個叫做Boot Block(引導塊)的區域,在計算機啟動過程中起著至關重要的作用,它是計算機啟動過程的起點,沒有引導塊中的引導代碼,計算機就無法知道如何加載操作系統,也就無法正常啟動

我們按照知識理解易難順序倒著往前來說

(一)數據塊 Data Blocks

用來存儲數據的塊,NAND FLASH 內部的數據塊由多個page組成,通常大小為4KB(現在也有8KB和16KB),這個page就是我們前面提到的最小寫入單位:頁

【Linux】緩沖區和文件系統

(二)inode表 inode Table

inode全稱為索引節點,是一種數據結構,用于存儲單個文件的全部屬性,一般來說每個文件都有一個inode

代碼語言:JavaScript代碼運行次數:0運行復制

struct inode{//inode編號//文件類型//權限//引用計數//擁有者//所屬組    // 直接塊指針    unsigned long i_block[NUM];    // 一次間接塊指針    unsigned long i_ind_block;    // 二次間接塊指針    unsigned long i_dind_block;    // 三次間接塊指針    unsigned long i_tind_block;}

其中inode編號每個文件都是不同的,我們主要說說數據塊指針

(1)直接塊指針

直接塊指針的NUM一般是12,它指向的位置是我們可以直接用來存儲的位置,如果我們內容比較小(12*4KB = 48KB以內),那么直接塊指針可以直接訪問這些數據

(2)一次間接塊指針

如果內容大于48KB,就需要一次間接塊指針,一次間接塊指針指向一個間接塊,這個間接塊存儲中存儲著多個指向數據塊的指針,如我們的內容在(4KB/4b)*4KB = 4MB以內,通過一次間接塊指針和直接塊指針就可以訪問這些數據

(3)二次間接塊指針

二次間接塊指針指向一個二次間接塊,這個二次間接塊存儲中存儲著多個指向間接塊的指針,與一次間接塊指針類似,這樣我們存儲的范圍就達到了(4KB/4b)*(4KB/4b)*4KB = 4GB

(4)三次間接塊指針

同上,最終我們最大的存儲范圍達到了 (4KB/4b)*(4KB/4b)*(4KB/4b)*4KB = 4TB

【Linux】緩沖區和文件系統

(三)inode位圖 inode Bitmap

我們通過位圖來和inode一一對應,位圖上對應的比特位為0,那么該inode就沒有被使用,可以被分配,如果為1則被占用,當從1變為0時,該inode又可以被分配了,其實這個過程就是一個刪除的過程,一旦一個文件的inode無了,那么這文件是真的無了

在文件系統中,標識文件不是看它的名字,而是看它的inode,一旦inode和文件取消綁定了,那么操作系統就找不到這個文件了,再次寫入其他內容的時候也就會被擦除覆蓋了,換而言之,刪除恒等于可以被覆蓋

(四)塊位圖 Block Bitmap

我們通過位圖來和數據塊page一一對應,位圖上對應的比特位為0,那么該頁page就沒有被使用,可以被分配,如果為1則被占用,當從1變為0時,該page又可以被分配了,如果我們要刪除一塊空間,只需要將它的對應的位置0,到再次被寫入的時候就會消失了,當然我們的NAND閃存是定期擦除的,過一段時間它自己就被擦除了

【Linux】緩沖區和文件系統

(五)塊組描述符表 Group Descriptor Table

記錄了該塊組的詳細信息,包括塊位圖的位置、inode 位圖的位置、inode 表的起始位置等,用于定位和管理塊組內的各種數據結構

(六)超級塊 Super Block

超級塊是文件系統的核心,記錄了文件系統的全局信息,如塊大小、inode 數量、空閑塊數量等,為了防止超級塊損壞導致文件系統無法使用,每個塊組中可能會包含超級塊的副本,不過并非所有塊組都有

? 版權聲明
THE END
喜歡就支持一下吧
點贊8 分享