詳解Linux文件中的數(shù)據(jù)是如何被寫進磁盤
一、操作系統(tǒng)對物理內(nèi)存的管理
1.1 物理內(nèi)存與磁盤的數(shù)據(jù)交換
物理內(nèi)存與磁盤之間的數(shù)據(jù)交換一般是以 4KB(大小可改) 為單位進行的,其中物理內(nèi)存中一個 4KB 大小的空間叫做頁框,填入 4KB 內(nèi)存中的內(nèi)容叫做頁幀。樣做的好處有以下幾點:
減少 I/O 的次數(shù),即減少 CPU 訪問外設(shè)的次數(shù)以提高效率。一次訪問 4KB 和分四次訪問 1KB 相比,前者效率更高,因為前者 CPU 只和磁盤只打了一次交道,磁頭和盤面只需要進行一次定位就可以讀取出 4KB 的內(nèi)容,而后者 CPU 和磁盤要打四次交到,并且這四次可能并不連續(xù),意味著磁頭和盤面要定位四次,大量的機械運動就伴隨著效率的下降。
基于局部性原理的預(yù)加載機制。即使當前 CPU 只需要訪問100字節(jié)的內(nèi)容,但操作系統(tǒng)和磁盤之間還是以 4KB 為單位將數(shù)據(jù)加載進來,一般認為,CPU 在訪問當前磁盤中的代碼和數(shù)據(jù)的時候,接下來有較大的可能性去訪問附近空間的代碼和數(shù)據(jù)。
小Tips:4KB 是科學家經(jīng)過大量實現(xiàn)確定出來的一個較為合理的值。一個文件如果占用了多個數(shù)據(jù)塊,那么只有最后一個數(shù)據(jù)塊可能存在沒用完浪費的情況。一個數(shù)據(jù)塊只能被一個文件使用。加入有兩個只有幾個比特的小文件,那么會為他們倆一人分配一個數(shù)據(jù)塊,他們兩個不可能共享同一個數(shù)據(jù)塊。
1.2 操作系統(tǒng)對物理內(nèi)存的管理
首先操作系統(tǒng)一定是可以看到物理內(nèi)存的。對物理內(nèi)存的管理還是逃不脫先描述再組織,在內(nèi)核中有一個 struct page
的結(jié)構(gòu)體就是用來描述物理內(nèi)存的,一個 struct page
對象就對應(yīng)一個 4KB 的內(nèi)存空間,該結(jié)構(gòu)體里面記錄了當前 4KB 的一些屬性信息,例如:當前頁框的狀態(tài),當前頁框的引用計數(shù)等。操作系統(tǒng)將物理內(nèi)存劃分成一個個的 struct page
對象,然后用數(shù)組的形式組織起來,數(shù)組的下標就是對應(yīng)的頁號。隨便給一個物理地址(一般一個物理地址對應(yīng)一個字節(jié))求它所在的頁號,就是用該物理地址除以 (4KB*1024 = 4096字節(jié))即可,也就是用該地址按位與上 0XFFFFF000
,將低12位清零,就是該地址所在的頁號。所有申請內(nèi)存的動作都是在訪問內(nèi)存 page 數(shù)組,查看 struct page
里面的 flags 屬性,通過 flags 屬性判斷當前頁框的狀態(tài),得知該頁框是否被使用,沒被使用就去修改 flags,表示該頁框已被申請。flags c除了可以表示當前頁框是否被使用外,還可以用來表示該頁框是只讀的還是讀寫等狀態(tài)。這里所說的操作系統(tǒng)對物理內(nèi)存的管理只是一個雛形,真正的內(nèi)存管理系統(tǒng)是非常復(fù)雜的,像伙伴系統(tǒng)算法、slab 分派器等。
二、再來看文件打開和寫入
2.1 文件頁緩沖區(qū)的引入
struct file 是內(nèi)核中的一個數(shù)據(jù)結(jié)構(gòu),用來描述一個打開的文件。而 inode 是在介紹磁盤時引入的,磁盤上的一個文件對應(yīng)一個 inode,它表示該文件的屬性。struct file 和 inode 之間的關(guān)系是,struct file 中只記錄了文件的少量屬性,因此在內(nèi)核中還有一個 struct inode 結(jié)構(gòu)體專門用來記錄一個文件的所有屬性。在 struct file 中有一個指針字段指向該文件的 struct inode 對象。
而文件是包括內(nèi)容加屬性的,在磁盤上文件的屬性用 inode 來存儲,文件的內(nèi)容用 block 來存儲,上面說過在內(nèi)核中用 struct inode 來存儲文件屬性,那一個文件的內(nèi)容(數(shù)據(jù))在內(nèi)核中該如何表示呢?答案是采用文件頁緩沖區(qū)。在 struct file 結(jié)構(gòu)中有一個 struct address_space 字段的指針,該結(jié)構(gòu)體里面有一個 struct radix_tree_root 結(jié)構(gòu)體對象,這本質(zhì)上是一個樹狀結(jié)構(gòu)(基數(shù)數(shù)又或叫字典書),樹中的每個節(jié)點都是 struct radix_tree_node 類型,該類型里面有一個名為 slots 的 void * 類型的數(shù)組,里面存的其實就是 struct page 對象的地址??偨Y(jié)一下就是在 struct file 結(jié)構(gòu)體中有指向物理內(nèi)存的指針,我們將這些物理內(nèi)存就叫做文件頁緩沖區(qū)。
2.2 向文件中寫入的過程
在調(diào)用 C/C++ 庫函數(shù)向文件中寫入,首先將內(nèi)容寫入到語言層面的用戶緩沖區(qū),然后再在合適的時機將內(nèi)容寫入到該文件對應(yīng)的文件頁緩沖區(qū)中,最后再在合適的時機將內(nèi)容寫入到外設(shè)。將物理內(nèi)存中的數(shù)據(jù)刷新到磁盤是由 I/O 子系統(tǒng)來執(zhí)行,進程并不會關(guān)心,在操作系統(tǒng)中一定會存在非常多的 I/O 操作,可能會有很多進程都要將數(shù)據(jù)寫入磁盤,操作系統(tǒng)會將所有的 I/O 操作根據(jù)先描述再組織的形式管理起來。內(nèi)核中的 struct request 結(jié)構(gòu)就是專門用來描述一個 I/O 操作的。為了提高 I/O 的效率,操作系統(tǒng)還會進行 I/O 排序和 I/O 合并,以減少磁頭和盤面的定位次數(shù)。
總結(jié):Linux 中,我們的每一個進程,打開的每一個文件都要有自己的 struct inode
對象和自己的文件頁緩沖區(qū)(就是所謂的內(nèi)核緩沖區(qū))。
三、結(jié)語
以上就是詳解Linux文件中的數(shù)據(jù)是如何被寫進磁盤的詳細內(nèi)容,更多關(guān)于Linux文件數(shù)據(jù)寫進磁盤的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
linux系統(tǒng)用戶管理與grep正則表達式示例教程
這篇文章主要給大家介紹了關(guān)于linux系統(tǒng)用戶管理與grep正則表達式的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用linux系統(tǒng)具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。2018-03-03Linux系統(tǒng)配置網(wǎng)絡(luò)詳細介紹
大家好,本篇文章主要講的是Linux系統(tǒng)配置網(wǎng)絡(luò)詳細介紹,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2022-01-01使用 bind 設(shè)置 DNS 服務(wù)器的方法
Bind9是一個強大的Linux下開放源代碼的DNS服務(wù)器軟件,這篇文章主要介紹了使用 bind 設(shè)置 DNS 服務(wù)器的方法,需要的朋友可以參考下2020-03-03Centos7的Firewalld防火墻基礎(chǔ)命令詳解
這篇文章主要介紹了Centos7的Firewalld防火墻基礎(chǔ)命令詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-11-11