多核CPU的TLB競(jìng)爭(zhēng):如何降低跨核刷新開(kāi)銷
頁(yè)表緩存(Page Table Cache)是Linux內(nèi)核中的一項(xiàng)關(guān)鍵機(jī)制,用于提高虛擬地址到物理地址轉(zhuǎn)換的性能。它在操作系統(tǒng)內(nèi)部維護(hù)了一個(gè)緩存,用來(lái)存儲(chǔ)最近訪問(wèn)過(guò)的頁(yè)表項(xiàng)。
當(dāng)程序訪問(wèn)虛擬地址時(shí),需要將其轉(zhuǎn)換為物理地址才能進(jìn)行實(shí)際的讀寫(xiě)操作。這個(gè)轉(zhuǎn)換過(guò)程涉及到查找對(duì)應(yīng)的頁(yè)表項(xiàng),并且可能會(huì)導(dǎo)致缺頁(yè)異常等開(kāi)銷較大的操作。為了減少這種開(kāi)銷,Linux內(nèi)核引入了頁(yè)表緩存。當(dāng)某個(gè)虛擬頁(yè)面第一次被訪問(wèn)時(shí),相應(yīng)的頁(yè)表項(xiàng)會(huì)被加載到頁(yè)表緩存中。如果之后再次訪問(wèn)同樣的虛擬頁(yè)面,就可以直接從頁(yè)表緩存中獲取對(duì)應(yīng)的頁(yè)表項(xiàng),避免了頻繁地查找和加載。
通過(guò)使用頁(yè)表緩存,Linux內(nèi)核能夠顯著提升虛擬地址到物理地址轉(zhuǎn)換的速度,從而加快系統(tǒng)的響應(yīng)和執(zhí)行效率。不過(guò)需要注意,在多處理器或多核系統(tǒng)上,由于存在并發(fā)訪問(wèn)和一致性問(wèn)題,對(duì)于共享數(shù)據(jù)結(jié)構(gòu)如頁(yè)表緩存的設(shè)計(jì)與管理需要特別小心。
一、頁(yè)表緩存簡(jiǎn)介
1.1虛擬與物理的橋梁
在計(jì)算機(jī)的世界里,內(nèi)存是數(shù)據(jù)和程序運(yùn)行的舞臺(tái)。其中,有兩個(gè)關(guān)鍵概念:虛擬內(nèi)存與物理內(nèi)存。物理內(nèi)存,就像是計(jì)算機(jī)實(shí)實(shí)在在擁有的 “舞臺(tái)場(chǎng)地”,由內(nèi)存條提供,程序運(yùn)行時(shí)的指令和數(shù)據(jù)會(huì)臨時(shí)存儲(chǔ)在這個(gè)物理空間中 ,它的容量受限于硬件配置,像我們常見(jiàn)的 8GB、16GB 、32GB 內(nèi)存規(guī)格,便是物理內(nèi)存的大小體現(xiàn)。而虛擬內(nèi)存,則像是一個(gè) “虛擬的大舞臺(tái)”,操作系統(tǒng)通過(guò)將硬盤的一部分空間模擬成內(nèi)存來(lái)實(shí)現(xiàn)。當(dāng)物理內(nèi)存不夠用時(shí),它就會(huì)把暫時(shí)不用的數(shù)據(jù)從物理內(nèi)存轉(zhuǎn)移到硬盤上的虛擬內(nèi)存區(qū)域,等需要的時(shí)候再取回來(lái)。這種機(jī)制使得程序可以使用比實(shí)際物理內(nèi)存更大的內(nèi)存空間,就好像給計(jì)算機(jī) “借” 了更多的場(chǎng)地來(lái)表演。
不過(guò),虛擬內(nèi)存和物理內(nèi)存之間存在著一個(gè)關(guān)鍵問(wèn)題:地址轉(zhuǎn)換。程序使用的是虛擬地址,而實(shí)際的數(shù)據(jù)存儲(chǔ)在物理內(nèi)存中,這就需要一種機(jī)制將虛擬地址轉(zhuǎn)換為物理地址,才能準(zhǔn)確地訪問(wèn)到數(shù)據(jù)。頁(yè)表,就是實(shí)現(xiàn)這個(gè)轉(zhuǎn)換的關(guān)鍵數(shù)據(jù)結(jié)構(gòu),它記錄了虛擬地址和物理地址之間的映射關(guān)系。但頁(yè)表通常存放在內(nèi)存中,每次地址轉(zhuǎn)換都要訪問(wèn)內(nèi)存中的頁(yè)表,而內(nèi)存訪問(wèn)速度相對(duì)較慢,這就像每次找東西都要去一個(gè)比較遠(yuǎn)的倉(cāng)庫(kù)(內(nèi)存)查清單(頁(yè)表),效率不高。
這時(shí),頁(yè)表緩存(Translation Lookaside Buffer,TLB)就登場(chǎng)了,它就像是一個(gè)放在身邊的 “快速清單”。TLB 是一種高速緩存,位于 CPU 的內(nèi)存管理單元(MMU)中,專門用于存儲(chǔ)虛擬地址到物理地址的映射關(guān)系 。當(dāng) CPU 需要訪問(wèn)一個(gè)虛擬地址時(shí),會(huì)首先在 TLB 中查找對(duì)應(yīng)的物理地址,如果找到了,就可以直接訪問(wèn)物理地址對(duì)應(yīng)的內(nèi)存,這就大大加快了地址轉(zhuǎn)換的速度,如同直接在身邊的快速清單里找到了要找東西的位置,無(wú)需再跑去遠(yuǎn)處的倉(cāng)庫(kù)查清單,極大地提高了內(nèi)存訪問(wèn)的效率。頁(yè)表緩存雖小,卻在虛擬內(nèi)存與物理內(nèi)存之間搭建起了一座高速橋梁,是計(jì)算機(jī)高效運(yùn)行不可或缺的關(guān)鍵角色。
1.2虛擬地址到物理地址的映射過(guò)程
虛擬地址到物理地址的映射過(guò)程是通過(guò)頁(yè)表完成的。在使用虛擬內(nèi)存時(shí),操作系統(tǒng)將物理內(nèi)存劃分成固定大小的頁(yè)面(通常為4KB),并將每個(gè)進(jìn)程的虛擬地址空間劃分成相同大小的頁(yè)面。
當(dāng)程序訪問(wèn)虛擬地址時(shí),CPU會(huì)將該虛擬地址發(fā)送給內(nèi)存管理單元(MMU),其中包含一個(gè)頁(yè)表基址寄存器(Page Table Base Register, PTBR)指向當(dāng)前進(jìn)程的頁(yè)表。
映射過(guò)程如下:
- CPU將虛擬地址發(fā)送給MMU。
- MMU根據(jù)虛擬地址中的頁(yè)號(hào)找到對(duì)應(yīng)的頁(yè)表項(xiàng)。
- 如果頁(yè)表項(xiàng)中標(biāo)記為有效,則獲取對(duì)應(yīng)的物理頁(yè)框號(hào)。
- 將物理頁(yè)框號(hào)與虛擬地址中的偏移量組合,得到最終的物理地址。
- 將最終物理地址返回給CPU,程序可以訪問(wèn)該物理地址上存儲(chǔ)的數(shù)據(jù)。
如果在步驟3中發(fā)現(xiàn)頁(yè)表項(xiàng)無(wú)效,則表示所請(qǐng)求的頁(yè)面不在物理內(nèi)存中。這時(shí)可能觸發(fā)缺頁(yè)異常,操作系統(tǒng)需要從磁盤上加載對(duì)應(yīng)頁(yè)面,并更新頁(yè)表項(xiàng)以建立新的映射關(guān)系。
(1)虛擬地址到物理地址轉(zhuǎn)換機(jī)制
①當(dāng)應(yīng)用程序需要訪問(wèn)內(nèi)存時(shí),會(huì)生成一個(gè)虛擬地址。這個(gè)虛擬地址由兩個(gè)部分組成:頁(yè)號(hào)和偏移量。
圖片
②操作系統(tǒng)將虛擬地址中的頁(yè)號(hào)與頁(yè)面表進(jìn)行匹配,找到對(duì)應(yīng)的Page Table Entry(PTE)。
③如果PTE中記錄了該頁(yè)面在物理內(nèi)存中的位置,則操作系統(tǒng)將物理內(nèi)存地址和偏移量組合成一個(gè)物理地址,并返回給應(yīng)用程序。如果PTE中未記錄該頁(yè)面在物理內(nèi)存中的位置,則產(chǎn)生一個(gè)缺頁(yè)異常。
圖片
④在發(fā)生缺頁(yè)異常時(shí),操作系統(tǒng)會(huì)嘗試從磁盤或其他存儲(chǔ)設(shè)備上加載相應(yīng)頁(yè)面,并更新PTE以反映新頁(yè)面所處的位置。
圖片
⑤一旦新頁(yè)面加載到物理內(nèi)存中,操作系統(tǒng)就可以使用步驟3中描述的方式來(lái)計(jì)算出該頁(yè)面在物理內(nèi)存中的位置,并返回給應(yīng)用程序。
這樣,在之后訪問(wèn)同一段虛擬地址時(shí),就不需要再次發(fā)生缺頁(yè)異常,而是直接查找PTE并返回對(duì)應(yīng)的物理地址。
(2)線性地址和虛擬地址之間的關(guān)系
線性地址是CPU產(chǎn)生的地址,它是由段選擇符和偏移量組成。在進(jìn)行內(nèi)存訪問(wèn)時(shí),CPU會(huì)將線性地址轉(zhuǎn)換為物理地址,并將數(shù)據(jù)從物理內(nèi)存中讀取或?qū)懭搿R虼?,線性地址是在CPU內(nèi)部使用的,不直接對(duì)應(yīng)物理內(nèi)存中的位置。而虛擬地址則是應(yīng)用程序使用的地址,它也由兩部分組成:頁(yè)號(hào)和偏移量。虛擬地址對(duì)應(yīng)了應(yīng)用程序所需訪問(wèn)的具體數(shù)據(jù)塊在邏輯上的位置。操作系統(tǒng)會(huì)負(fù)責(zé)將虛擬地址轉(zhuǎn)換為物理地址,并實(shí)現(xiàn)內(nèi)存訪問(wèn)。
在這個(gè)過(guò)程中,操作系統(tǒng)采用了一些技術(shù)來(lái)實(shí)現(xiàn)虛擬地址到物理地址的轉(zhuǎn)換。例如,在32位x86架構(gòu)中常用的方法是利用分頁(yè)機(jī)制(paging),將整個(gè)邏輯空間劃分為大小相等、連續(xù)編號(hào)的頁(yè)面(page)。每個(gè)頁(yè)面包含若干個(gè)字節(jié),并且與一個(gè)PTE相對(duì)應(yīng)。PTE記錄了該頁(yè)面是否已經(jīng)加載到物理內(nèi)存中以及其在物理內(nèi)存中的位置等信息。
當(dāng)應(yīng)用程序需要訪問(wèn)某個(gè)虛擬地址時(shí),操作系統(tǒng)首先根據(jù)虛擬地址的頁(yè)號(hào)查找PTE,如果該頁(yè)面已經(jīng)在物理內(nèi)存中,則可以通過(guò)PTE計(jì)算出對(duì)應(yīng)的物理地址,并將數(shù)據(jù)從物理內(nèi)存中讀取或?qū)懭?。否則,就會(huì)發(fā)生缺頁(yè)異常,并且操作系統(tǒng)需要將相應(yīng)頁(yè)面從磁盤或其他存儲(chǔ)設(shè)備上加載到物理內(nèi)存中。
因此,線性地址和虛擬地址之間存在一定的關(guān)系。在32位x86架構(gòu)中,線性地址是由段選擇符和偏移量組成的,而偏移量部分直接對(duì)應(yīng)了虛擬地址的偏移量部分。同時(shí),在進(jìn)行內(nèi)存訪問(wèn)時(shí),CPU會(huì)自動(dòng)執(zhí)行線性地址到物理地址的轉(zhuǎn)換,并且可以利用硬件支持來(lái)提高訪問(wèn)速度。
圖片
二、頁(yè)表緩存是什么
頁(yè)表緩存,全稱是 Translation Lookaside Buffer,簡(jiǎn)稱 TLB ,也常被叫做快表,從專業(yè)角度來(lái)講,它是一種用于提高虛擬地址到物理地址轉(zhuǎn)換速度的硬件緩存機(jī)制。
在計(jì)算機(jī)系統(tǒng)中,CPU 運(yùn)行程序時(shí)產(chǎn)生的是虛擬地址,而數(shù)據(jù)實(shí)際存儲(chǔ)在物理內(nèi)存中,這中間就需要頁(yè)表來(lái)完成虛擬地址到物理地址的映射。然而,頁(yè)表存放在內(nèi)存里,每次查詢頁(yè)表都要訪問(wèn)內(nèi)存,內(nèi)存訪問(wèn)速度相對(duì)較慢,這就好比每次找東西都要去較遠(yuǎn)的倉(cāng)庫(kù)翻清單,效率不高。
TLB 就如同在身邊設(shè)置的一個(gè)快速清單。它集成在 CPU 的內(nèi)存管理單元(MMU)中,是一種高速緩存,專門用來(lái)存放近期使用過(guò)的虛擬地址與物理地址的映射關(guān)系 。當(dāng) CPU 要訪問(wèn)一個(gè)虛擬地址時(shí),會(huì)先到 TLB 里查找對(duì)應(yīng)的物理地址。要是找到了(這就是命中),就能直接用找到的物理地址去訪問(wèn)內(nèi)存,極大地加快了地址轉(zhuǎn)換速度;要是沒(méi)找到(即未命中),CPU 就會(huì)去內(nèi)存中的頁(yè)表查詢物理地址,然后把新的映射關(guān)系存入 TLB,方便下次快速查找 ??梢哉f(shuō),TLB 雖然容量不大,卻在虛擬內(nèi)存和物理內(nèi)存之間搭建起了一座高速橋梁,大大提升了內(nèi)存訪問(wèn)效率,是計(jì)算機(jī)系統(tǒng)高效運(yùn)行的關(guān)鍵一環(huán)。
三、頁(yè)表緩存的工作原理
3.1地址查詢
當(dāng)處理器需要訪問(wèn)內(nèi)存時(shí),會(huì)如同在圖書(shū)館查找一本急需的書(shū)籍一般,首先在頁(yè)表緩存這個(gè) “快速索引區(qū)” 查找所需的虛擬地址到物理地址的映射。假設(shè)我們正在運(yùn)行一個(gè)辦公軟件,當(dāng)軟件中的程序指令需要讀取存儲(chǔ)在內(nèi)存中的用戶文檔數(shù)據(jù)時(shí),CPU會(huì)產(chǎn)生一個(gè)虛擬地址。
這個(gè)虛擬地址就像是一個(gè)帶有編號(hào)的 “虛擬書(shū)架位置”,CPU拿著這個(gè)編號(hào)先來(lái)到頁(yè)表緩存這個(gè)“快速清單”前查找。如果在頁(yè)表緩存中找到了匹配的條目,也就是命中了,就好比在快速索引區(qū)找到了這本書(shū)的實(shí)際書(shū)架位置,CPU可以直接獲取對(duì)應(yīng)的物理地址,從而避免了訪問(wèn)內(nèi)存中完整的頁(yè)表,大大提高了地址轉(zhuǎn)換速度,快速讀取到所需的數(shù)據(jù),讓辦公軟件能流暢地將文檔內(nèi)容展示在用戶面前 。
3.2緩存更新
要是在頁(yè)表緩存中未找到所需的映射,即未命中,情況就像在快速索引區(qū)沒(méi)找到那本書(shū)的位置,處理器就不得不去內(nèi)存中的頁(yè)表這個(gè) “完整藏書(shū)目錄” 查詢物理地址。當(dāng)完成查詢,得到新的物理地址后,處理器會(huì)如同將新書(shū)的位置信息補(bǔ)充到快速索引區(qū)一樣,將新的映射關(guān)系添加到頁(yè)表緩存中,以便后續(xù)再次訪問(wèn)相同虛擬地址時(shí)能夠更快地找到對(duì)應(yīng)的物理地址 。
為了保證頁(yè)表緩存始終能高效工作,在添加新映射時(shí),如果緩存已滿,就需要按照一定的替換策略,將那些不常用的條目替換出去,比如采用最近最少使用(LRU)策略,把長(zhǎng)時(shí)間未被訪問(wèn)的映射條目替換掉,讓頁(yè)表緩存時(shí)刻保持 “新鮮”,隨時(shí)為快速地址轉(zhuǎn)換服務(wù),確保計(jì)算機(jī)系統(tǒng)的高效運(yùn)行 。
3.3頁(yè)表緩存的特點(diǎn)剖析
(1)高速緩存
頁(yè)表緩存堪稱計(jì)算機(jī)硬件世界里的 “短跑冠軍”,它通常由高速硬件打造而成,要么是專用的高速緩存芯片,如同為其量身定制的高性能裝備;要么直接集成在處理器內(nèi)部,與處理器緊密協(xié)作,就像親密無(wú)間的伙伴,能在極短時(shí)間內(nèi)完成地址查詢,訪問(wèn)延遲低至幾個(gè)時(shí)鐘周期 。
與之形成鮮明對(duì)比的是內(nèi)存訪問(wèn),內(nèi)存訪問(wèn)速度相對(duì)較慢,每次查詢內(nèi)存中的頁(yè)表,都如同在一條漫長(zhǎng)的道路上行走,需要經(jīng)過(guò)內(nèi)存總線等硬件設(shè)備,可能要耗費(fèi)多個(gè)時(shí)鐘周期才能完成一次訪問(wèn)。在計(jì)算機(jī)運(yùn)行過(guò)程中,若每次地址轉(zhuǎn)換都依賴內(nèi)存訪問(wèn)頁(yè)表,系統(tǒng)性能將會(huì)大幅下降,就像一個(gè)人背著沉重的包袱跑步,速度會(huì)大受影響。而頁(yè)表緩存的高速特性,使得 CPU 在進(jìn)行地址轉(zhuǎn)換時(shí),能快速獲取所需的物理地址,極大地提升了系統(tǒng)性能,讓計(jì)算機(jī)的運(yùn)行更加流暢高效,如同為計(jì)算機(jī)插上了高速飛行的翅膀 。
(2)小容量
由于成本和芯片面積等因素的限制,頁(yè)表緩存的容量相對(duì)較小,通常只能存儲(chǔ)幾百到幾千個(gè)映射條目,就像一個(gè)空間有限的小型倉(cāng)庫(kù) 。在實(shí)際應(yīng)用中,計(jì)算機(jī)系統(tǒng)運(yùn)行的程序眾多,進(jìn)程的虛擬地址空間龐大,頁(yè)表中記錄的虛擬地址到物理地址的映射關(guān)系數(shù)量巨大,相比之下,頁(yè)表緩存的容量就顯得捉襟見(jiàn)肘。
當(dāng)處理器訪問(wèn)的虛擬地址在頁(yè)表緩存中未命中時(shí),就不得不去內(nèi)存中查詢頁(yè)表,這不僅增加了地址轉(zhuǎn)換的時(shí)間,還可能導(dǎo)致系統(tǒng)性能的波動(dòng)。為了應(yīng)對(duì)這一挑戰(zhàn),計(jì)算機(jī)系統(tǒng)采用了多種策略,比如優(yōu)化頁(yè)面置換算法,像最近最少使用(LRU)算法,優(yōu)先替換長(zhǎng)時(shí)間未被訪問(wèn)的映射條目,確保緩存中始終保留最有可能被再次訪問(wèn)的映射關(guān)系;還有預(yù)取技術(shù),操作系統(tǒng)根據(jù)程序的執(zhí)行路徑和內(nèi)存訪問(wèn)模式,提前將可能需要的頁(yè)表項(xiàng)預(yù)取到頁(yè)表緩存中,提高緩存命中率,以充分發(fā)揮頁(yè)表緩存的作用 。
(3)關(guān)聯(lián)性
頁(yè)表緩存一般采用組相聯(lián)或全相聯(lián)的映射方式,來(lái)提高緩存的命中率,就像精心規(guī)劃的分類存放系統(tǒng) 。以組相聯(lián)映射為例,頁(yè)表緩存被巧妙地分為多個(gè)組,每個(gè)組內(nèi)又包含多個(gè)緩存行,宛如一個(gè)大型圖書(shū)館被劃分成多個(gè)書(shū)架區(qū)域,每個(gè)書(shū)架區(qū)域里又有多層書(shū)架。
當(dāng)處理器拿著虛擬地址來(lái)查詢物理地址時(shí),虛擬地址會(huì)根據(jù)其索引字段映射到特定的組,這就如同根據(jù)書(shū)籍的分類編號(hào)快速找到對(duì)應(yīng)的書(shū)架區(qū)域。然后在組內(nèi)進(jìn)行查找,就像在特定書(shū)架區(qū)域的多層書(shū)架中尋找具體的書(shū)籍。這種映射方式,相比直接映射緩存,能在同一組內(nèi)存儲(chǔ)多個(gè)頁(yè)表項(xiàng),降低了因地址沖突導(dǎo)致的緩存未命中情況。比如,當(dāng)不同的虛擬地址映射到相同的緩存位置(即地址沖突)時(shí),如果是直接映射緩存,就只能保留一個(gè)映射關(guān)系,其他的會(huì)被覆蓋,導(dǎo)致后續(xù)訪問(wèn)可能未命中;而組相聯(lián)映射方式,由于同一組內(nèi)可以存放多個(gè)映射關(guān)系,就大大減少了這種沖突,提高了緩存命中率,使得頁(yè)表緩存能更高效地為地址轉(zhuǎn)換服務(wù) 。
四、Linux內(nèi)核頁(yè)表結(jié)構(gòu)
在Linux內(nèi)核中,頁(yè)表是用來(lái)管理虛擬內(nèi)存和物理內(nèi)存之間映射關(guān)系的數(shù)據(jù)結(jié)構(gòu)。Linux采用了兩級(jí)頁(yè)表(two-level page table)的結(jié)構(gòu),具體包括以下幾個(gè)部分:
- 一級(jí)頁(yè)表(Level 1 Page Table):也稱為頂層頁(yè)表(Top-Level Page Table),它是整個(gè)頁(yè)表層次結(jié)構(gòu)的入口點(diǎn)。一級(jí)頁(yè)表的條目數(shù)與物理內(nèi)存大小相關(guān),每個(gè)條目指向二級(jí)頁(yè)表。
- 二級(jí)頁(yè)表(Level 2 Page Table):也稱為中間層頁(yè)表(Intermediate Page Table)。二級(jí)頁(yè)表將虛擬地址空間劃分成更小的區(qū)域,并對(duì)應(yīng)到三級(jí)頁(yè)表。
- 三級(jí)頁(yè)表(Level 3 Page Table):也稱為底層頁(yè)表(Leaf Page Table)。三級(jí)頁(yè)表對(duì)應(yīng)著最細(xì)粒度的頁(yè)面大小,通常是4KB或2MB。每個(gè)條目包含了虛擬地址和物理地址之間的映射關(guān)系。
通過(guò)多級(jí)頁(yè)表結(jié)構(gòu),Linux 內(nèi)核能夠有效地管理大型虛擬地址空間和物理內(nèi)存。當(dāng)進(jìn)程訪問(wèn)一個(gè)虛擬地址時(shí),內(nèi)核會(huì)根據(jù)虛擬地址在不同層次的頁(yè)表中進(jìn)行查找和轉(zhuǎn)換,最終得到對(duì)應(yīng)的物理地址。
需要注意的是,在64位版本的 Linux 內(nèi)核中,由于更廣闊的虛擬地址空間和更大容量的物理內(nèi)存支持,可能會(huì)有更多級(jí)的頁(yè)表結(jié)構(gòu)。具體的層次結(jié)構(gòu)和細(xì)節(jié)可能因不同的架構(gòu)、配置和內(nèi)核版本而有所變化,上述描述僅為一般情況下的常見(jiàn)頁(yè)表結(jié)構(gòu)。
4.1頁(yè)表項(xiàng)
頁(yè)表項(xiàng)(Page Table Entry)是頁(yè)表中的每個(gè)條目,用于描述虛擬地址與物理地址之間的映射關(guān)系。每個(gè)頁(yè)表項(xiàng)通常包含以下字段:
- 物理頁(yè)面基址(Physical Page Base Address):指向?qū)?yīng)的物理內(nèi)存頁(yè)面的起始地址。
- 標(biāo)志位(Flags):用于控制頁(yè)面的訪問(wèn)權(quán)限、緩存策略和其他特性。常見(jiàn)的標(biāo)志位包括可讀/寫(xiě)/執(zhí)行權(quán)限、緩存禁用、全局標(biāo)志等。
- 狀態(tài)位(Status Bits):記錄頁(yè)面的狀態(tài)信息,如臟頁(yè)標(biāo)記、引用位等。
- 其他輔助字段:可能包含一些額外信息,如頁(yè)表層次索引、保留位等。
根據(jù)操作系統(tǒng)和硬件架構(gòu)的不同,頁(yè)表項(xiàng)可能有不同的結(jié)構(gòu)和長(zhǎng)度。例如,在x86體系結(jié)構(gòu)上,一個(gè)典型的32位頁(yè)表項(xiàng)長(zhǎng)度為4字節(jié)(32 bits),而在64位上則是8字節(jié)(64 bits)。這些長(zhǎng)度限制了能夠表示的物理內(nèi)存大小和虛擬地址空間范圍。
通過(guò)逐級(jí)查找和解析頁(yè)表項(xiàng),操作系統(tǒng)可以將虛擬地址轉(zhuǎn)換為物理地址,并進(jìn)行訪問(wèn)控制和管理。因此,正確配置和使用頁(yè)表項(xiàng)對(duì)于有效管理內(nèi)存和實(shí)現(xiàn)安全性至關(guān)重要。
4.1各種類型的頁(yè)面
- Page Table Entry (PTE):記錄了一個(gè)頁(yè)面在物理內(nèi)存中的地址以及相關(guān)信息,用于虛擬地址到物理地址的映射。
- Page Global Directory (PGD):一種高級(jí)頁(yè)表結(jié)構(gòu),用于管理大量虛擬內(nèi)存。它將多個(gè)Page Table組織起來(lái),形成更大的虛擬地址空間。
- Page Middle Directory (PMD):類似于PGD,但粒度更小。通常用于管理特定區(qū)域內(nèi)的虛擬內(nèi)存。
- Inverted Page Table (IPT):與傳統(tǒng)頁(yè)表不同,IPT根據(jù)物理地址索引每個(gè)頁(yè)面對(duì)應(yīng)的虛擬地址和進(jìn)程信息。它可以減少頁(yè)表占用的內(nèi)存,并提高查找效率。
- Translation Lookaside Buffer (TLB):高速緩存,位于CPU芯片上,加速虛擬地址到物理地址轉(zhuǎn)換過(guò)程。
4.3頁(yè)表緩存與頁(yè)表的關(guān)系解讀
頁(yè)表緩存與頁(yè)表,雖然都服務(wù)于虛擬地址到物理地址的轉(zhuǎn)換,但它們?cè)谟?jì)算機(jī)系統(tǒng)中扮演著截然不同的角色 。
從定義上看,頁(yè)表是一種數(shù)據(jù)結(jié)構(gòu),就像一本詳細(xì)的 “地址映射大全”,它完整記錄了虛擬地址空間中的頁(yè)與物理內(nèi)存中的頁(yè)框之間的映射關(guān)系,是虛擬內(nèi)存管理的核心所在,為操作系統(tǒng)實(shí)現(xiàn)虛擬內(nèi)存到物理內(nèi)存的轉(zhuǎn)換提供了最基礎(chǔ)的依據(jù) 。而頁(yè)表緩存,即快表(TLB),則像是從這本 “地址映射大全” 中精選出來(lái)的 “常用地址速查表”,是一種高速緩存機(jī)制,專門用于緩存頁(yè)表中最近使用的映射關(guān)系,是對(duì)頁(yè)表部分內(nèi)容進(jìn)行快速存儲(chǔ)和訪問(wèn)的硬件結(jié)構(gòu) 。
在作用方面,頁(yè)表承擔(dān)著實(shí)現(xiàn)虛擬地址到物理地址完整映射的重任,操作系統(tǒng)依靠它來(lái)管理進(jìn)程的虛擬地址空間,進(jìn)行內(nèi)存分配、回收以及地址轉(zhuǎn)換等一系列關(guān)鍵操作,確保每個(gè)進(jìn)程都能在自己獨(dú)立的虛擬地址空間中準(zhǔn)確無(wú)誤地訪問(wèn)內(nèi)存,實(shí)現(xiàn)內(nèi)存的有效隔離和保護(hù) 。頁(yè)表緩存的主要作用則是加速這一地址轉(zhuǎn)換過(guò)程,通過(guò)緩存最近使用的頁(yè)表項(xiàng),減少訪問(wèn)內(nèi)存中頁(yè)表的次數(shù),就像為地址轉(zhuǎn)換開(kāi)辟了一條高速通道,從而顯著提高地址轉(zhuǎn)換速度,提升整個(gè)系統(tǒng)的運(yùn)行性能 。
存儲(chǔ)位置與訪問(wèn)速度上,二者也有很大差異。頁(yè)表通常存儲(chǔ)在主內(nèi)存中,由于內(nèi)存訪問(wèn)需要經(jīng)過(guò)內(nèi)存總線等硬件設(shè)備,就像要穿過(guò)一條漫長(zhǎng)的通道才能到達(dá),每次訪問(wèn)可能需要多個(gè)時(shí)鐘周期才能完成,速度相對(duì)較慢 。頁(yè)表緩存一般集成在處理器內(nèi)部,或者靠近處理器的高速緩存芯片中,離處理器非常近,能在幾個(gè)時(shí)鐘周期內(nèi)快速完成地址查詢,極大地縮短了地址轉(zhuǎn)換時(shí)間,就像在處理器身邊隨時(shí)待命,快速響應(yīng)地址轉(zhuǎn)換請(qǐng)求 。
從數(shù)據(jù)結(jié)構(gòu)與容量來(lái)看,頁(yè)表是一個(gè)完整且通常較為龐大的數(shù)據(jù)結(jié)構(gòu),包含了進(jìn)程虛擬地址空間中所有頁(yè)與物理內(nèi)存頁(yè)框的映射關(guān)系,其大小取決于虛擬地址空間的大小和頁(yè)的大小等因素,可能會(huì)占用大量的內(nèi)存空間 。頁(yè)表緩存的數(shù)據(jù)結(jié)構(gòu)相對(duì)簡(jiǎn)單,主要包含虛擬頁(yè)號(hào)、物理頁(yè)框號(hào)等關(guān)鍵信息,以及一些用于管理和查找的標(biāo)志位等,其容量相對(duì)較小,通常只能存儲(chǔ)幾百到幾千個(gè)映射條目 。
在數(shù)據(jù)更新與維護(hù)方面,頁(yè)表由操作系統(tǒng)在進(jìn)行內(nèi)存管理操作,如進(jìn)程創(chuàng)建、內(nèi)存分配、頁(yè)面置換等時(shí)進(jìn)行更新和維護(hù),以確保虛擬地址到物理地址映射的正確性和完整性 。頁(yè)表緩存一方面會(huì)在操作系統(tǒng)更新頁(yè)表時(shí),根據(jù)更新策略相應(yīng)地更新緩存中的條目;另一方面,在發(fā)生地址轉(zhuǎn)換時(shí),如果在頁(yè)表緩存中未命中,會(huì)從頁(yè)表中加載新的映射關(guān)系到頁(yè)表緩存中,并根據(jù)替換策略替換掉不常用的條目 。頁(yè)表緩存就像是頁(yè)表的 “高速助手”,雖然依賴于頁(yè)表,但通過(guò)自身的特性,大大提升了地址轉(zhuǎn)換的效率,與頁(yè)表共同協(xié)作,保障計(jì)算機(jī)系統(tǒng)的高效運(yùn)行 。
4.4頁(yè)表緩存的重要性與應(yīng)用場(chǎng)景
在計(jì)算機(jī)系統(tǒng)中,頁(yè)表緩存(TLB)就像一個(gè)隱藏在幕后卻掌控全局的關(guān)鍵角色,其重要性不言而喻,在提升內(nèi)存訪問(wèn)效率和系統(tǒng)整體性能方面發(fā)揮著不可替代的作用 。
從內(nèi)存訪問(wèn)效率來(lái)看,頁(yè)表緩存是加速地址轉(zhuǎn)換的 “加速器”。在沒(méi)有頁(yè)表緩存的情況下,每次內(nèi)存訪問(wèn)都需要查詢內(nèi)存中的頁(yè)表,由于內(nèi)存訪問(wèn)速度相對(duì)較慢,這會(huì)大大增加地址轉(zhuǎn)換的時(shí)間。而頁(yè)表緩存的存在,使得 CPU 能夠在極短時(shí)間內(nèi)完成地址轉(zhuǎn)換,快速獲取所需數(shù)據(jù),減少了處理器等待數(shù)據(jù)的時(shí)間,讓計(jì)算機(jī)能夠高效運(yùn)行。例如,在程序運(yùn)行過(guò)程中,頻繁地訪問(wèn)內(nèi)存中的指令和數(shù)據(jù),如果每次都要經(jīng)過(guò)漫長(zhǎng)的頁(yè)表查詢過(guò)程,程序的執(zhí)行速度將大幅下降,而頁(yè)表緩存的高速特性則有效避免了這種情況,確保程序能夠流暢運(yùn)行 。
從系統(tǒng)整體性能角度而言,頁(yè)表緩存對(duì)提升系統(tǒng)性能有著至關(guān)重要的影響。它能夠顯著提高 CPU 的利用率,因?yàn)闇p少了內(nèi)存訪問(wèn)的延遲,CPU 可以更快地執(zhí)行指令,從而提高整個(gè)系統(tǒng)的吞吐量。在多任務(wù)處理環(huán)境下,頁(yè)表緩存使得不同進(jìn)程之間的切換更加高效,每個(gè)進(jìn)程都能快速訪問(wèn)自己的內(nèi)存空間,減少了進(jìn)程上下文切換帶來(lái)的開(kāi)銷,提高了系統(tǒng)的并發(fā)處理能力,讓計(jì)算機(jī)能夠同時(shí)處理多個(gè)復(fù)雜任務(wù)而不卡頓 。
頁(yè)表緩存的身影廣泛出現(xiàn)在各類計(jì)算機(jī)應(yīng)用場(chǎng)景中 。在操作系統(tǒng)運(yùn)行時(shí),頁(yè)表緩存為操作系統(tǒng)的高效運(yùn)行提供了有力支持。操作系統(tǒng)需要頻繁地訪問(wèn)內(nèi)存中的各種數(shù)據(jù)結(jié)構(gòu)和程序代碼,頁(yè)表緩存能夠快速完成地址轉(zhuǎn)換,使得操作系統(tǒng)能夠及時(shí)響應(yīng)各種系統(tǒng)調(diào)用和中斷請(qǐng)求,保證系統(tǒng)的穩(wěn)定性和流暢性 。比如在 Windows 系統(tǒng)中,當(dāng)用戶打開(kāi)多個(gè)應(yīng)用程序時(shí),操作系統(tǒng)通過(guò)頁(yè)表緩存快速管理各個(gè)應(yīng)用程序的內(nèi)存訪問(wèn),確保系統(tǒng)的高效運(yùn)行 。
在大型軟件運(yùn)行時(shí),頁(yè)表緩存同樣發(fā)揮著關(guān)鍵作用。像3D游戲、視頻編輯軟件等大型軟件,它們通常需要處理大量的數(shù)據(jù)和復(fù)雜的圖形渲染任務(wù),對(duì)內(nèi)存訪問(wèn)的速度要求極高。頁(yè)表緩存能夠快速將虛擬地址轉(zhuǎn)換為物理地址,讓軟件能夠快速讀取和處理所需的數(shù)據(jù),保證軟件的流暢運(yùn)行,為用戶提供更好的使用體驗(yàn) 。以熱門的 3D 游戲?yàn)槔螒蛑械膱?chǎng)景渲染、角色動(dòng)作等都需要大量的數(shù)據(jù)支持,頁(yè)表緩存能夠快速響應(yīng)游戲?qū)?nèi)存的訪問(wèn)請(qǐng)求,使得游戲畫(huà)面更加流暢,避免出現(xiàn)卡頓現(xiàn)象 。
在服務(wù)器環(huán)境中,頁(yè)表緩存更是不可或缺。服務(wù)器需要同時(shí)處理大量的客戶端請(qǐng)求,對(duì)系統(tǒng)性能和穩(wěn)定性要求極高。頁(yè)表緩存能夠提高服務(wù)器對(duì)內(nèi)存的訪問(wèn)效率,加快數(shù)據(jù)的處理速度,從而提高服務(wù)器的并發(fā)處理能力,確保服務(wù)器能夠穩(wěn)定地為大量用戶提供服務(wù) 。例如,在電商網(wǎng)站的服務(wù)器中,在購(gòu)物高峰期,大量用戶同時(shí)訪問(wèn)網(wǎng)站進(jìn)行商品瀏覽、下單等操作,頁(yè)表緩存能夠幫助服務(wù)器快速處理這些請(qǐng)求,保證網(wǎng)站的正常運(yùn)行 。
五、頁(yè)表緩存原理
由于頁(yè)表存放在主存中,因此程序每次訪存至少需要兩次:一次訪存獲取物理地址,第二次訪存才獲得數(shù)據(jù)。提高訪存性能的關(guān)鍵在于依靠頁(yè)表的訪問(wèn)局部性。當(dāng)一個(gè)轉(zhuǎn)換的虛擬頁(yè)號(hào)被使用時(shí),它可能在不久的將來(lái)再次被使用到,。
TLB是一種高速緩存,內(nèi)存管理硬件使用它來(lái)改善虛擬地址到物理地址的轉(zhuǎn)換速度。當(dāng)前所有的個(gè)人桌面,筆記本和服務(wù)器處理器都使用TLB來(lái)進(jìn)行虛擬地址到物理地址的映射。使用TLB內(nèi)核可以快速的找到虛擬地址指向物理地址,而不需要請(qǐng)求RAM內(nèi)存獲取虛擬地址到物理地址的映射關(guān)系。這與data cache和instruction caches有很大的相似之處。
TLB的原理如下:
- 當(dāng)CPU訪問(wèn)一個(gè)虛擬地址時(shí),首先檢查TLB中是否有對(duì)應(yīng)的頁(yè)表項(xiàng)。
- 如果TLB中有對(duì)應(yīng)的頁(yè)表項(xiàng)(即命中),則直接從TLB獲取物理地址。
- 如果TLB中沒(méi)有對(duì)應(yīng)的頁(yè)表項(xiàng)(即未命中),則需要訪問(wèn)內(nèi)存來(lái)獲取正確的頁(yè)表項(xiàng)。
- 在未命中情況下,操作系統(tǒng)會(huì)進(jìn)行相應(yīng)處理,從主存中獲取正確的頁(yè)表項(xiàng),并將其加載到TLB中以供后續(xù)使用。
- 一旦正確的頁(yè)表項(xiàng)加載到TLB中,CPU再次訪問(wèn)相同虛擬地址時(shí)就可以直接在TLB中找到映射關(guān)系,提高了轉(zhuǎn)換效率。
TLB具有快速查找和高效緩存機(jī)制,能夠極大地減少查詢頁(yè)表所需的時(shí)間。然而,由于TLB是有限容量的,在大型程序或多任務(wù)環(huán)境下可能無(wú)法完全覆蓋所有需要轉(zhuǎn)換的頁(yè)面。當(dāng)發(fā)生TLB未命中時(shí),則會(huì)導(dǎo)致額外的內(nèi)存訪問(wèn)開(kāi)銷;操作系統(tǒng)會(huì)負(fù)責(zé)管理和維護(hù)TLB,包括緩存策略、TLB的刷新機(jī)制等。常見(jiàn)的緩存策略有全相聯(lián)、組相聯(lián)和直接映射等。
5.1TLB原理
當(dāng)cpu要訪問(wèn)一個(gè)虛擬地址/線性地址時(shí),CPU會(huì)首先根據(jù)虛擬地址的高20位(20是x86特定的,不同架構(gòu)有不同的值)在TLB中查找。如果是表中沒(méi)有相應(yīng)的表項(xiàng),稱為TLB miss,需要通過(guò)訪問(wèn)慢速RAM中的頁(yè)表計(jì)算出相應(yīng)的物理地址。同時(shí),物理地址被存放在一個(gè)TLB表項(xiàng)中,以后對(duì)同一線性地址的訪問(wèn),直接從TLB表項(xiàng)中獲取物理地址即可,稱為TLB hit。
想像一下x86_32架構(gòu)下沒(méi)有TLB的存在時(shí)的情況,對(duì)線性地址的訪問(wèn),首先從PGD中獲取PTE(第一次內(nèi)存訪問(wèn)),在PTE中獲取頁(yè)框地址(第二次內(nèi)存訪問(wèn)),最后訪問(wèn)物理地址,總共需要3次RAM的訪問(wèn)。如果有TLB存在,并且TLB hit,那么只需要一次RAM訪問(wèn)即可。
5.2TLB表項(xiàng)
TLB內(nèi)部存放的基本單位是頁(yè)表?xiàng)l目,對(duì)應(yīng)著RAM中存放的頁(yè)表?xiàng)l目。頁(yè)表?xiàng)l目的大小固定不變的,所以TLB容量越大,所能存放的頁(yè)表?xiàng)l目越多,TLB hit的幾率也越大。但是TLB容量畢竟是有限的,因此RAM頁(yè)表和TLB頁(yè)表?xiàng)l目無(wú)法做到一一對(duì)應(yīng)。因此CPU收到一個(gè)線性地址,那么必須快速做兩個(gè)判斷:
- 所需的也表示否已經(jīng)緩存在TLB內(nèi)部(TLB miss或者TLB hit)
- 所需的頁(yè)表在TLB的哪個(gè)條目?jī)?nèi)
為了盡量減少CPU做出這些判斷所需的時(shí)間,那么就必須在TLB頁(yè)表?xiàng)l目和內(nèi)存頁(yè)表?xiàng)l目之間的對(duì)應(yīng)方式做足功夫
全相連 - full associative
在這種組織方式下,TLB cache中的表項(xiàng)和線性地址之間沒(méi)有任何關(guān)系,也就是說(shuō),一個(gè)TLB表項(xiàng)可以和任意線性地址的頁(yè)表項(xiàng)關(guān)聯(lián)。這種關(guān)聯(lián)方式使得TLB表項(xiàng)空間的利用率最大。但是延遲也可能相當(dāng)?shù)拇?,因?yàn)槊看蜟PU請(qǐng)求,TLB硬件都把線性地址和TLB的表項(xiàng)逐一比較,直到TLB hit或者所有TLB表項(xiàng)比較完成。特別是隨著CPU緩存越來(lái)越大,需要比較大量的TLB表項(xiàng),所以這種組織方式只適合小容量TLB
直接匹配
每一個(gè)線性地址塊都可通過(guò)模運(yùn)算對(duì)應(yīng)到唯一的TLB表項(xiàng),這樣只需進(jìn)行一次比較,降低了TLB內(nèi)比較的延遲。但是這個(gè)方式產(chǎn)生沖突的幾率非常高,導(dǎo)致TLB miss的發(fā)生,降低了命中率。
比如,我們假定TLB cache共包含16個(gè)表項(xiàng),CPU順序訪問(wèn)以下線性地址塊:1, 17 , 1, 33。當(dāng)CPU訪問(wèn)地址塊1時(shí),1 mod 16 = 1,TLB查看它的第一個(gè)頁(yè)表項(xiàng)是否包含指定的線性地址塊1,包含則命中,否則從RAM裝入;然后CPU方位地址塊17,17 mod 16 = 1,TLB發(fā)現(xiàn)它的第一個(gè)頁(yè)表項(xiàng)對(duì)應(yīng)的不是線性地址塊17,TLB miss發(fā)生,TLB訪問(wèn)RAM把地址塊17的頁(yè)表項(xiàng)裝入TLB;CPU接下來(lái)訪問(wèn)地址塊1,此時(shí)又發(fā)生了miss,TLB只好訪問(wèn)RAM重新裝入地址塊1對(duì)應(yīng)的頁(yè)表項(xiàng)。因此在某些特定訪問(wèn)模式下,直接匹配的性能差到了極點(diǎn)
組相連 - set-associative
為了解決全相連內(nèi)部比較效率低和直接匹配的沖突,引入了組相連。這種方式把所有的TLB表項(xiàng)分成多個(gè)組,每個(gè)線性地址塊對(duì)應(yīng)的不再是一個(gè)TLB表項(xiàng),而是一個(gè)TLB表項(xiàng)組。CPU做地址轉(zhuǎn)換時(shí),首先計(jì)算線性地址塊對(duì)應(yīng)哪個(gè)TLB表項(xiàng)組,然后在這個(gè)TLB表項(xiàng)組順序比對(duì)。按照組長(zhǎng)度,我們可以稱之為2路,4路,8路。
經(jīng)過(guò)長(zhǎng)期的工程實(shí)踐,發(fā)現(xiàn)8路組相連是一個(gè)性能分界點(diǎn)。8路組相連的命中率幾乎和全相連命中率幾乎一樣,超過(guò)8路,組內(nèi)對(duì)比延遲帶來(lái)的缺點(diǎn)就超過(guò)命中率提高帶來(lái)的好處了。
這三種方式各有優(yōu)缺點(diǎn),組相連是個(gè)折衷的選擇,適合大部分應(yīng)用環(huán)境。當(dāng)然針對(duì)不同的領(lǐng)域,也可以采用其他的cache組織形式。
TLB表項(xiàng)更新
TLB表項(xiàng)更新可以有TLB硬件自動(dòng)發(fā)起,也可以有軟件主動(dòng)更新
- TLB miss發(fā)生后,CPU從RAM獲取頁(yè)表項(xiàng),會(huì)自動(dòng)更新TLB表項(xiàng)
- TLB中的表項(xiàng)在某些情況下是無(wú)效的,比如進(jìn)程切換,更改內(nèi)核頁(yè)表等,此時(shí)CPU硬件不知道哪些TLB表項(xiàng)是無(wú)效的,只能由軟件在這些場(chǎng)景下,刷新TLB。
在linux kernel軟件層,提供了豐富的TLB表項(xiàng)刷新方法,但是不同的體系結(jié)構(gòu)提供的硬件接口不同。比如x86_32僅提供了兩種硬件接口來(lái)刷新TLB表項(xiàng):
- 向cr3寄存器寫(xiě)入值時(shí),會(huì)導(dǎo)致處理器自動(dòng)刷新非全局頁(yè)的TLB表項(xiàng)
- 在Pentium Pro以后,invlpg匯編指令用來(lái)無(wú)效指定線性地址的單個(gè)TLB表項(xiàng)無(wú)效。
內(nèi)核對(duì)頁(yè)緩存的操作函數(shù)
內(nèi)核對(duì)頁(yè)緩存的基本操作包含了在一個(gè)頁(yè)緩存所形成的radix樹(shù)中查找,增加和刪除一個(gè)頁(yè)緩存?;趓adix的基本操作函數(shù),頁(yè)高速緩存的處理函數(shù)如下:
- page_cache_alloc():分配一個(gè)新的頁(yè)緩存;
- find_get_page():在頁(yè)高速緩存中查找指定頁(yè);
- add_to_page_cache():把一個(gè)新頁(yè)添加到頁(yè)高速緩存;
- remove_from_page_cache():將指定頁(yè)從頁(yè)高速緩存中移除;
- read_cache_page():確保指定頁(yè)在頁(yè)高速緩存中包含最新的數(shù)據(jù);