中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開(kāi)通VIP
計(jì)算機(jī)底層知識(shí)拾遺(六)理解頁(yè)緩存page cache和地址空間address

在這篇計(jì)算機(jī)底層知識(shí)拾遺(五)理解塊IO層 中講了塊緩存buffer cache塊緩存,這篇說(shuō)說(shuō)頁(yè)緩存page cache以及相關(guān)的地址空間address_space的要點(diǎn)。

在Linux 2.4內(nèi)核中塊緩存buffer cache和頁(yè)緩存page cache是并存的,表現(xiàn)的現(xiàn)象是同一份文件的數(shù)據(jù),可能即出現(xiàn)在buffer cache中,又出現(xiàn)在頁(yè)緩存中,這樣就造成了物理內(nèi)存的浪費(fèi)。Linux 2.6內(nèi)核對(duì)兩個(gè)cache進(jìn)行了合并,統(tǒng)一使用頁(yè)緩存在做緩存,只有極少數(shù)的情況下才使用到buffer cache。后面會(huì)說(shuō)buffer cache和page cache的區(qū)別。先直觀看看兩者的容量是如何統(tǒng)計(jì)的。

在 /proc/meminfo中存儲(chǔ)了當(dāng)前系統(tǒng)的內(nèi)存使用情況,比如下面這個(gè)例子,

Buffers表示buffer cache的容量

Cached表示位于物理內(nèi)存中的頁(yè)緩存page cache

SwapCached表示位于磁盤交換區(qū)的頁(yè)緩存page cache

所以實(shí)際頁(yè)緩存page cache的容量 =  Cached + SwapCached


buffer cache和page cache的區(qū)別


buffer cache是Unix和早期的Linux內(nèi)核中主要的緩存組件。我們要理解的是不管是buffer cache還是page cache都是為了處理塊設(shè)備和內(nèi)存交互時(shí)高速訪問(wèn)的問(wèn)題

1. buffer cache是面向底層塊設(shè)備的,所以它的粒度是文件系統(tǒng)的塊,塊設(shè)備和系統(tǒng)采用塊進(jìn)行交互。塊再轉(zhuǎn)換成磁盤的基本物理結(jié)構(gòu)扇區(qū)。扇區(qū)的大小是512KB,而文件系統(tǒng)的塊一般是2KB, 4KB, 8KB。扇區(qū)和塊之間是可以快速轉(zhuǎn)換的

隨著內(nèi)核的功能越來(lái)越完善,塊粒度的緩存已經(jīng)不能滿足性能的需要。內(nèi)核的內(nèi)存管理組件采用了比文件系統(tǒng)的塊更高級(jí)別的抽象,頁(yè)page,頁(yè)的大小一般從4KB到2MB,粒度更大,處理的性能更高。所以緩存組件為了和內(nèi)存管理組件更好地交互,創(chuàng)建了頁(yè)緩存page cache來(lái)代替原來(lái)的buffer cache。

頁(yè)緩存是面向文件,面向內(nèi)存的。通過(guò)一系列的數(shù)據(jù)結(jié)構(gòu),比如inode, address_space, page,將一個(gè)文件映射到頁(yè)的級(jí)別,通過(guò)page + offset就可以定位到一個(gè)文件的具體位置

2. buffer cache實(shí)際操作時(shí)按塊為基本單位,page cache操作時(shí)按頁(yè)為基本單位,新建了一個(gè)BIO的抽象,可以同時(shí)處理多個(gè)非連續(xù)的頁(yè)的IO操作,也就是所謂的scatter/gather IO

3. buffer cache目前主要用在需要按塊傳輸?shù)膱?chǎng)景下,比如超級(jí)塊的讀寫等。而page cache可以用在所有以文件為單元的場(chǎng)景下,比如網(wǎng)絡(luò)文件系統(tǒng)等等,緩存組件抽象了地址空間address_space這個(gè)概念來(lái)作為文件系統(tǒng)和頁(yè)緩存的中間適配器,屏蔽了底層設(shè)備的細(xì)節(jié)

4. buffer cache可以和page cache集成在一起,屬于一個(gè)page的塊緩存使用buffer_head鏈表的方式組織,page_cache維護(hù)了一個(gè)private指針指向這個(gè)buffer_head鏈表,buffer_head鏈表維護(hù)了一個(gè)指針指向這個(gè)頁(yè)page。這樣只需要在頁(yè)緩存中存儲(chǔ)一份數(shù)據(jù)即可

5. 文件系統(tǒng)的inode實(shí)際維護(hù)了這個(gè)文件所有的塊block的塊號(hào),通過(guò)對(duì)文件偏移量offset取模可以很快定位到這個(gè)偏移量所在的文件系統(tǒng)的塊號(hào),磁盤的扇區(qū)號(hào)。同樣,通過(guò)對(duì)文件偏移量offset進(jìn)行取??梢杂?jì)算出偏移量所在的頁(yè)的偏移量,地址空間address_space通過(guò)指針可以方便的獲取兩端inode和page的信息,所以可以很方便地定位到一個(gè)文件的offset在各個(gè)組件中的位置:

文件字節(jié)偏移量 --> 頁(yè)偏移量 --> 文件系統(tǒng)塊號(hào) block  -->  磁盤扇區(qū)號(hào)


頁(yè)緩存page cache和地址空間address_space


上面比較page cache和buffer cache的時(shí)候基本把page cache的特點(diǎn)說(shuō)了,它是面向內(nèi)存,面向文件的。這正好說(shuō)明了頁(yè)緩存的作用,它位于內(nèi)存和文件之間,文件IO操作實(shí)際上只和頁(yè)緩存交互,不直接和內(nèi)存交互。

Linux內(nèi)核使用page數(shù)據(jù)結(jié)構(gòu)來(lái)描述物理內(nèi)存頁(yè)幀,內(nèi)核創(chuàng)建了mem_map數(shù)組來(lái)表示所有的物理頁(yè)幀,mem_map的數(shù)組項(xiàng)就是page。

page結(jié)構(gòu)不僅表示了物理內(nèi)存頁(yè)幀,

1. 一些標(biāo)志位flags來(lái)表示該頁(yè)是否是臟頁(yè),是否正在被寫回等等

2. _count, _mapcount表示這個(gè)頁(yè)被多少個(gè)進(jìn)程使用和映射

3. private指針指向了這個(gè)頁(yè)對(duì)應(yīng)的buffer cache的buffer_head鏈表,建立了頁(yè)緩存和塊緩存的聯(lián)系

4. mapping指向了地址空間address_space,表示這個(gè)頁(yè)是一個(gè)頁(yè)緩存中頁(yè),和一個(gè)文件的地址空間對(duì)應(yīng)

5. index是這個(gè)頁(yè)在文件中的頁(yè)偏移量,通過(guò)文件的字節(jié)偏移量可以計(jì)算出文件的頁(yè)偏移量



頁(yè)緩存實(shí)際上就是采用了一個(gè)基數(shù)樹結(jié)構(gòu)將一個(gè)文件的內(nèi)容組織起來(lái)存放在物理內(nèi)存page中。文件IO操作直接和頁(yè)緩存交互。采用緩存原理來(lái)管理塊設(shè)備的IO操作


一個(gè)文件inode對(duì)應(yīng)一個(gè)地址空間address_space。而一個(gè)address_space對(duì)應(yīng)一個(gè)頁(yè)緩存基數(shù)樹。這幾個(gè)組件的關(guān)系如下



再看一下地址空間address_space的概念。address_space是Linux內(nèi)核中的一個(gè)關(guān)鍵抽象,它是頁(yè)緩存和外部設(shè)備中文件系統(tǒng)的橋梁,可以說(shuō)關(guān)聯(lián)了內(nèi)存系統(tǒng)和文件系統(tǒng),文件系統(tǒng)可以理解成數(shù)據(jù)源。

1. inode指向這個(gè)地址空間的宿主,也就是數(shù)據(jù)源

2. page_tree指向了這個(gè)地址空間對(duì)應(yīng)的頁(yè)緩存的基數(shù)樹。這樣就可以通過(guò)inode --> address_space -->  page_tree找打一個(gè)文件對(duì)應(yīng)的頁(yè)緩存頁(yè)




讀文件時(shí),首先通過(guò)要讀取的文件內(nèi)容的偏移量offset計(jì)算出要讀取的頁(yè),然后通過(guò)該文件的inode找到這個(gè)文件對(duì)應(yīng)的地址空間address_space,然后在address_space中訪問(wèn)該文件的頁(yè)緩存,如果頁(yè)緩存命中,那么直接返回文件內(nèi)容,如果頁(yè)緩存缺失,那么產(chǎn)生一個(gè)頁(yè)缺失異常,創(chuàng)業(yè)一個(gè)頁(yè)緩存頁(yè),然后從磁盤中讀取相應(yīng)文件的頁(yè)填充該緩存頁(yè),租后從頁(yè)缺失異常中恢復(fù),繼續(xù)往下讀。

寫文件時(shí),首先通過(guò)所寫內(nèi)容在文件中的偏移量計(jì)算出相應(yīng)的頁(yè),然后還是通過(guò)inode找到address_space,通過(guò)address_space找到頁(yè)緩存中頁(yè),如果頁(yè)緩存命中,直接把文件內(nèi)容修改更新在頁(yè)緩存的頁(yè)中。寫文件就結(jié)束了。這時(shí)候文件修改位于頁(yè)緩存,并沒(méi)有寫回writeback到磁盤文件中去。

一個(gè)頁(yè)緩存中的頁(yè)如果被修改,那么會(huì)被標(biāo)記成臟頁(yè)。臟頁(yè)需要寫回到磁盤中的文件塊。有兩種方式可以把臟頁(yè)寫回磁盤,也就是flush。

1. 手動(dòng)調(diào)用sync()或者fsync()系統(tǒng)調(diào)用把臟頁(yè)寫回

2. pdflush進(jìn)程會(huì)定時(shí)把臟頁(yè)寫回到磁盤


臟頁(yè)不能被置換出內(nèi)存,如果臟頁(yè)正在被寫回,那么會(huì)被設(shè)置寫回標(biāo)記,這時(shí)候該頁(yè)就被上鎖,其他寫請(qǐng)求被阻塞直到鎖釋放


在某些情況下我們可能需要繞過(guò)頁(yè)緩存機(jī)制,比如系統(tǒng)存在大日志的情況,比如數(shù)據(jù)庫(kù)系統(tǒng),日志不會(huì)被經(jīng)常重復(fù)讀取,如果都緩存在內(nèi)存中會(huì)影響系統(tǒng)的性能。內(nèi)核提供了直接IO的方式,O_DIRECT,可以繞過(guò)頁(yè)緩存,直接把文件內(nèi)容從堆中寫到磁盤文件。



關(guān)于文件IO我們常說(shuō)兩句話“普通文件IO需要復(fù)制兩次,內(nèi)存映射文件mmap復(fù)制一次”,"普通文件IO是堆內(nèi)操作,內(nèi)存映射文件是堆外操作"。我們來(lái)看一下這兩句話。

對(duì)于普通文件需要復(fù)制兩次,我們要理解到底是哪兩次,大部分的書都沒(méi)說(shuō)清楚,只說(shuō)是第一次復(fù)制是從磁盤到內(nèi)存緩沖區(qū),第二次是從內(nèi)存緩沖區(qū)到進(jìn)程的堆。這里的內(nèi)存緩沖區(qū)實(shí)際上就是頁(yè)緩存。

這篇文件Page Cache, the Affair Between Memory and Files中的幾張圖很形象,說(shuō)明白了這中間實(shí)際發(fā)生底層操作。


加入一個(gè)進(jìn)程render要讀取一個(gè)scene.dat文件,實(shí)際發(fā)生的步驟如下

1. render進(jìn)程向內(nèi)核發(fā)起讀scene.dat文件的請(qǐng)求

2. 內(nèi)核根據(jù)scene.dat的inode找到對(duì)應(yīng)的address_space,在address_space中查找頁(yè)緩存,如果沒(méi)有找到,那么分配一個(gè)內(nèi)存頁(yè)page加入到頁(yè)緩存

3. 從磁盤中讀取scene.dat文件相應(yīng)的頁(yè)填充頁(yè)緩存中的頁(yè),也就是第一次復(fù)制

4. 從頁(yè)緩存的頁(yè)復(fù)制內(nèi)容到render進(jìn)程的堆空間的內(nèi)存中,也就是第二次復(fù)制



最后物理內(nèi)存的內(nèi)容是這樣的,同一個(gè)文件scene.dat的內(nèi)容存在了兩份拷貝,一份是頁(yè)緩存,一份是用戶進(jìn)程的堆空間對(duì)應(yīng)的物理內(nèi)存空間



再來(lái)看看內(nèi)存映射文件mmap只復(fù)制一次是如何做的,mmap只有一次頁(yè)緩存的復(fù)制,從磁盤文件復(fù)制到也緩存中。

mmap會(huì)創(chuàng)建一個(gè)虛擬內(nèi)存區(qū)域vm_area_struct,進(jìn)程的task_struct維護(hù)著這個(gè)進(jìn)程所有的虛擬內(nèi)存區(qū)域信息,虛擬內(nèi)存區(qū)域會(huì)更新相應(yīng)的進(jìn)程頁(yè)表項(xiàng),讓這些頁(yè)表項(xiàng)直接指向頁(yè)緩存所在的物理頁(yè)page。mmap新建的這個(gè)虛擬內(nèi)存區(qū)域和進(jìn)程堆的虛擬內(nèi)存區(qū)域不是同一個(gè),所以mmap是在堆外空間。


最后明確幾個(gè)概念

1. 用戶進(jìn)程訪問(wèn)內(nèi)存只能通過(guò)頁(yè)表結(jié)構(gòu),內(nèi)核可以通過(guò)虛擬地址直接訪問(wèn)物理內(nèi)存。

2. 用戶進(jìn)程不能訪問(wèn)內(nèi)核的地址空間,這里的地址空間指的是虛擬地址空間,這是肯定的,因?yàn)橛脩暨M(jìn)程的虛擬地址空間和內(nèi)核的虛擬地址空間是不重合的,內(nèi)核虛擬地址空間必須特權(quán)訪問(wèn)

3. page結(jié)構(gòu)表示物理內(nèi)存頁(yè)幀,同一個(gè)物理內(nèi)存地址可以同時(shí)被內(nèi)核進(jìn)程和用戶進(jìn)程訪問(wèn),只要將用戶進(jìn)程的頁(yè)表項(xiàng)也指向這個(gè)物理內(nèi)存地址。也就是mmap的實(shí)現(xiàn)原理。


參考資料:

Page Cache, the Affair Between Memory and Files

Linux Kernel: What is the major difference between the buffer cache and the page cache?

《深入Linux內(nèi)核架構(gòu)》


本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
linux內(nèi)核 address_space 結(jié)構(gòu)
從內(nèi)核文件系統(tǒng)看文件讀寫過(guò)程
linux下使用free命令查看實(shí)際內(nèi)存占用(可用內(nèi)存)
內(nèi)存不夠用還要速度快,終于找到可以基于 File 的 Cache 了
關(guān)于Linux Cache與Direct IO
Linux文件系統(tǒng)—源代碼導(dǎo)讀
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服