詳解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用戶建立腳本/猜字游戲/網(wǎng)卡流量監(jiān)控介紹
大家好,本篇文章主要講的是Linux用戶建立腳本/猜字游戲/網(wǎng)卡流量監(jiān)控介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下2021-12-12
在CentOS7/8系統(tǒng)上快速部署MinIO對(duì)象存儲(chǔ)服務(wù)的詳細(xì)步驟
在私有化部署對(duì)象存儲(chǔ)(OSS)的方案中,MinIO憑借其輕量級(jí)、高性能以及完美兼容 S3 協(xié)議的特性,已經(jīng)成為了開發(fā)和運(yùn)維的首選,今天我們不談虛的,直接上干貨,演示如何在最基礎(chǔ)的CentOS 7/8裸機(jī)環(huán)境下,實(shí)現(xiàn) 5 分鐘極速部署,需要的朋友可以參考下2026-03-03
Linux下安裝Python3和django并配置mysql作為django默認(rèn)服務(wù)器方法
下面小編就為大家?guī)硪黄狶inux下安裝Python3和django并配置mysql作為django默認(rèn)服務(wù)器方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-10-10
PHP程序員玩轉(zhuǎn)Linux系列 lnmp環(huán)境搭建
這篇文章主要為大家詳細(xì)介紹了PHP程序員玩轉(zhuǎn)Linux系列文章,lnmp環(huán)境搭建教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
Linux中搭建DNS域名解析服務(wù)器的詳細(xì)過程
在Linux中搭建DNS服務(wù)器涉及配置和運(yùn)行一個(gè)軟件來提供DNS服務(wù),DNS是互聯(lián)網(wǎng)上的一種系統(tǒng),它將域名轉(zhuǎn)換為對(duì)應(yīng)的IP地址,使得用戶可以通過易記的域名訪問網(wǎng)站,而不是記憶一長串?dāng)?shù)字,本文給大家詳細(xì)介紹了Linux中搭建DNS域名解析服務(wù)器,需要的朋友可以參考下2024-03-03
Windows 和 Linux 上Redis的安裝守護(hù)進(jìn)程配置方法
​ Redis是目前最常用的非關(guān)系型數(shù)據(jù)庫(NOSql)之一,常以Key-Value的形式存儲(chǔ)。這篇文章主要介紹了Windows 和 Linux 上Redis的安裝守護(hù)進(jìn)程配置 ,需要的朋友可以參考下2019-06-06
Apache?Ignite?中的?SQL?模式(Schema)管理機(jī)制(使用建議)
Apache?Ignite支持多Schema管理,包含默認(rèn)的PUBLIC和SYS系統(tǒng)Schema,允許自定義Schema通過配置或Cache名稱定義,DDL創(chuàng)建表時(shí)會(huì)自動(dòng)生成對(duì)應(yīng)Cache,建議合理使用Schema組織數(shù)據(jù)及權(quán)限控制,本文給大家介紹Apache?Ignite中的SQL模式(Schema)管理機(jī)制,感興趣的朋友一起看看吧2025-07-07

