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