自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux內(nèi)核內(nèi)存管理:分頁技術(shù)的核心原理

系統(tǒng) Linux
在 Linux 系統(tǒng)的廣袤天地里,內(nèi)存管理猶如一座精密復(fù)雜的大廈,而分頁機(jī)制則是這座大廈的基石。它就像是一位幕后英雄,默默地支撐著整個(gè)系統(tǒng)的穩(wěn)定運(yùn)行,讓眾多進(jìn)程能夠井然有序地共享物理內(nèi)存資源。

你有沒有想過,當(dāng)你在電腦上同時(shí)打開多個(gè)程序,一邊聽音樂、一邊寫文檔,還掛著下載任務(wù)時(shí),系統(tǒng)是怎么有條不紊地運(yùn)作,不讓這些程序“打架”爭內(nèi)存的呢?答案就藏在這神奇的分頁機(jī)制里。它就像是一位擁有超能力的空間魔法師,面對有限的物理內(nèi)存“空間”,大手一揮,將虛擬的邏輯地址空間和物理內(nèi)存空間,都精準(zhǔn)地劃分成了一塊塊同等大小、排列規(guī)整的“魔法方塊”——也就是頁。然后,憑借著一套如同精密齒輪組般的映射規(guī)則,讓每個(gè)程序都以為自己擁有了廣袤無垠的“專屬領(lǐng)地”,實(shí)則是在內(nèi)核的巧妙調(diào)配下,高效共享著物理內(nèi)存資源。

這不僅極大地提升了內(nèi)存利用率,避免了內(nèi)存碎片的“亂象”,更是為虛擬內(nèi)存的華麗登場鋪就了堅(jiān)實(shí)大道,讓我們的電腦仿佛擁有了無限擴(kuò)容的“超能力”?,F(xiàn)在,就請緊跟我的腳步,一起深入探究這分頁機(jī)制背后的奇妙故事,解鎖Linux內(nèi)核高效運(yùn)行的密碼吧!

一、分頁P(yáng)aging簡介

1.1什么是分頁?

在 Linux 系統(tǒng)的廣袤天地里,內(nèi)存管理猶如一座精密復(fù)雜的大廈,而分頁機(jī)制則是這座大廈的基石。它就像是一位幕后英雄,默默地支撐著整個(gè)系統(tǒng)的穩(wěn)定運(yùn)行,讓眾多進(jìn)程能夠井然有序地共享物理內(nèi)存資源。

想象一下,在計(jì)算機(jī)的世界中,眾多進(jìn)程如同一個(gè)個(gè)活躍的 “居民”,它們都渴望擁有自己的內(nèi)存空間來存儲數(shù)據(jù)、運(yùn)行程序。然而,物理內(nèi)存的容量是有限的,就好比一塊有限大小的土地,如何合理地分配給這些 “居民”,讓它們都能安居樂業(yè)呢?這便是分頁機(jī)制大展身手的時(shí)刻。

Linux 內(nèi)核通過分頁機(jī)制,將物理內(nèi)存劃分為一個(gè)個(gè)固定大小的 “小房間”,這些 “小房間” 被稱為頁。一般來說,常見的頁大小為 4KB 或 8KB,當(dāng)然,在不同的硬件架構(gòu)和系統(tǒng)配置下,頁大小可能會有所不同。與此同時(shí),虛擬內(nèi)存空間也被按照相同的頁大小進(jìn)行劃分。這樣一來,虛擬內(nèi)存中的每一頁都能找到與之對應(yīng)的物理內(nèi)存頁,就像給每個(gè) “居民” 都分配了一個(gè)專屬的小房間,它們通過 “門牌號”(地址映射)就能準(zhǔn)確無誤地找到自己的家。

這種分頁的方式帶來了諸多好處。一方面,它極大地簡化了內(nèi)存管理的復(fù)雜度。內(nèi)核只需關(guān)注這些固定大小的頁,而無需對每一個(gè)字節(jié)的內(nèi)存進(jìn)行精細(xì)管理,大大減輕了內(nèi)核的負(fù)擔(dān),就如同小區(qū)管理員只需管理一個(gè)個(gè)房間,而不用操心房間里每一塊磚的擺放。另一方面,分頁使得內(nèi)存的分配與回收變得更加高效。當(dāng)一個(gè)進(jìn)程需要內(nèi)存時(shí),內(nèi)核可以輕松地分配若干個(gè)連續(xù)或不連續(xù)的頁給它;當(dāng)進(jìn)程結(jié)束后,回收這些頁也變得輕而易舉,不會留下混亂的內(nèi)存碎片,保證了內(nèi)存空間的整潔有序,就像整理房間一樣,把不用的東西清理出去,為新的需求騰出空間。

再者,分頁機(jī)制為內(nèi)存的保護(hù)與共享提供了堅(jiān)實(shí)的保障。每個(gè)進(jìn)程都擁有自己獨(dú)立的頁表,這就好比每個(gè) “居民” 都有一把獨(dú)一無二的鑰匙,只能打開自己房間的門,從而有效地隔離了不同進(jìn)程的內(nèi)存空間,防止一個(gè)進(jìn)程誤闖另一個(gè)進(jìn)程的 “領(lǐng)地”,保障了系統(tǒng)的安全性。而且,通過巧妙的頁表映射,多個(gè)進(jìn)程還能共享同一段物理內(nèi)存,就像幾個(gè)朋友可以一起在客廳里玩耍,共享公共空間,實(shí)現(xiàn)了資源的高效利用,提升了系統(tǒng)的整體性能。

1.2為什么會有分頁機(jī)制?

如果沒有分頁機(jī)制,能否實(shí)現(xiàn)“虛擬內(nèi)存”?答案是肯定的。

圖片圖片

當(dāng)同時(shí)運(yùn)行的任務(wù)很多時(shí),內(nèi)存可能就不夠用,如上圖所示,每個(gè)段描述符都有 AVL 位(簡稱 A 位),用于表示一個(gè)段最近是否被訪問過(準(zhǔn)確地說是表明從上次操作系統(tǒng)清零該位后一個(gè)段是否被訪問過)。

當(dāng)創(chuàng)建描述符的時(shí)候,應(yīng)該把 A 位清零。之后,每當(dāng)該段被訪問時(shí),準(zhǔn)確地說是處理器把這個(gè)段的段選擇符加載進(jìn)段寄存器時(shí),CPU 就將該位置“1”;對該位的清零是由操作系統(tǒng)負(fù)責(zé)的,通過定期監(jiān)視該位的狀態(tài),就可以統(tǒng)計(jì)出該段的使用頻率(比如,每 1 秒鐘查看一次,一旦置位就清零,統(tǒng)計(jì) 10 秒鐘內(nèi)被置位了多少次,次數(shù)越多說明使用越頻繁)。當(dāng)內(nèi)存空間緊張時(shí),可以把不經(jīng)常使用的段退避到硬盤上,從而實(shí)現(xiàn)虛擬內(nèi)存管理。

當(dāng)某個(gè)段被換出到磁盤時(shí),操作系統(tǒng)應(yīng)該將這個(gè)段的描述符的 P 位清零。過上一段時(shí)間,當(dāng)再次訪問這個(gè)段時(shí),因?yàn)樗拿枋龇?P 位是 0,處理器就會引發(fā)段不存在異常(中斷號 11)。這類中斷通常是由操作系統(tǒng)處理的,它會用同樣的方法騰出空間,然后把這個(gè)段從磁盤調(diào)入內(nèi)存。當(dāng)這類中斷返回時(shí),處理器會再次執(zhí)行引發(fā)異常的那條指令,這時(shí)候段已經(jīng)在內(nèi)存中(P=1),于是程序又可以繼續(xù)執(zhí)行了。

由此可見,即使沒有分頁機(jī)制,利用“分段”也可以實(shí)現(xiàn)“虛擬內(nèi)存”。但是,因?yàn)槎蔚拈L度不固定,在段的換入換出時(shí)會產(chǎn)生外部碎片,這樣就浪費(fèi)了很多內(nèi)存。為了解決這個(gè)問題,從 80386 處理器開始,引入了分頁機(jī)制。分頁機(jī)制簡單來說,是用長度固定的頁來代替長度不定的段,以解決因段的長度不同帶來的內(nèi)存空間管理變得復(fù)雜的問題。盡管操作系統(tǒng)也可以利用純軟件來實(shí)施固定長度的內(nèi)存分配,但是過于復(fù)雜。由處理器固件來做這件事情,可以省去很多麻煩,速度也可以提高。總結(jié)一下,引入分頁機(jī)制并不是為了實(shí)現(xiàn)虛擬內(nèi)存,而是為了解決內(nèi)存碎片的問題。

二、分頁的核心構(gòu)成:頁表的神奇架構(gòu)

2.1頁表 —— 虛擬與物理的橋梁

在深入了解分頁機(jī)制時(shí),頁表無疑是其中最為關(guān)鍵的核心部件,它宛如一座神奇的橋梁,穩(wěn)穩(wěn)地架設(shè)在虛擬內(nèi)存和物理內(nèi)存之間,實(shí)現(xiàn)了二者之間的精準(zhǔn)映射。

當(dāng)進(jìn)程運(yùn)行時(shí),它所使用的是虛擬地址,這些虛擬地址就像是一系列抽象的 “房間編號”,進(jìn)程憑借這些編號去訪問內(nèi)存。然而,實(shí)際的數(shù)據(jù)存儲在物理內(nèi)存中,物理內(nèi)存有著自己真實(shí)的 “房間布局”。此時(shí),頁表就發(fā)揮作用了,它記錄著每一個(gè)虛擬頁號與對應(yīng)的物理頁框號之間的映射關(guān)系,就如同一張?jiān)敿?xì)的 “房間對照表”。

舉個(gè)例子,假設(shè)一個(gè)進(jìn)程發(fā)出了對虛擬地址 0x1234 的訪問請求,系統(tǒng)首先會將這個(gè)虛擬地址按照既定的頁大小規(guī)則,拆分成頁號和頁內(nèi)偏移量。比如,頁大小為 4KB(2^12 字節(jié)),0x1234 對應(yīng)的二進(jìn)制為 0001 0010 0011 0100,前幾位表示頁號,后 12 位表示頁內(nèi)偏移。接著,通過查詢頁表,找到與該頁號對應(yīng)的物理頁框號,假設(shè)是 0x56,再結(jié)合頁內(nèi)偏移量,就能準(zhǔn)確地定位到物理內(nèi)存中的實(shí)際存儲位置,完成數(shù)據(jù)的讀取或?qū)懭氩僮鳎麄€(gè)過程就像根據(jù)房間編號在對照表中找到真實(shí)房間位置一樣精準(zhǔn)高效。

而且,頁表不僅僅是簡單的地址映射,它還包含了豐富的控制信息。每個(gè)頁表項(xiàng)通常會設(shè)置一些標(biāo)志位,如讀寫權(quán)限位,用來控制進(jìn)程對該頁的訪問模式,防止進(jìn)程誤操作或惡意篡改數(shù)據(jù);還有存在位,用于標(biāo)識該頁當(dāng)前是否已經(jīng)加載到物理內(nèi)存中,若不存在,則可能觸發(fā)缺頁異常,促使內(nèi)核進(jìn)行相應(yīng)的頁面調(diào)度操作,確保進(jìn)程的順利運(yùn)行??梢哉f,頁表以其精妙的設(shè)計(jì),保障了內(nèi)存訪問的準(zhǔn)確性、安全性以及系統(tǒng)的穩(wěn)定性,是分頁機(jī)制得以順暢運(yùn)行的關(guān)鍵樞紐。

每級頁表由多個(gè)表項(xiàng)組成,頁表可以看做一個(gè)數(shù)組,而表項(xiàng)則是數(shù)組中的元素。各級頁表的表項(xiàng)格式比較類似,但并不完全相同。在 4 級分頁下,各級表項(xiàng)的名稱如下:

  • 4 級頁表項(xiàng)(PML4E)
  • 頁目錄指針表項(xiàng)(PDPTE,3 級頁表項(xiàng))
  • 頁目錄項(xiàng)( PDE ,2 級頁表項(xiàng))
  • 頁表項(xiàng)(PTE,1 級頁表項(xiàng))

其中,頁目錄指針表項(xiàng)(3 級頁表項(xiàng))和 頁目錄項(xiàng)(2 級頁表項(xiàng))可以直接映射到頁,也可以引用下級頁表。根據(jù)不同的映射情況,它們各自又有 2 種不同的格式。但頁目錄指針表項(xiàng)(3 級頁表項(xiàng))直接映射到頁時(shí),頁的大小為 1GB,這種大頁很少使用,而且不是所有處理器都支持,所以我們不做介紹。

在各級表項(xiàng)中,除了包含下級頁表的物理地址之外,還有各種標(biāo)志位,我們稱之為頁標(biāo)志或者頁屬性。直接映射到頁的表項(xiàng)和引用了其它頁表的表項(xiàng),其標(biāo)志位是不同的。

當(dāng)表項(xiàng)直接映射到頁時(shí),它啟用了 Dirty 標(biāo)志位(臟位,位 6)、Global 標(biāo)志位(全局標(biāo)志位,位 8)以及 PAT 標(biāo)志位( Page Attribute Table,位 7 或 位12);否則,這 3 個(gè)標(biāo)志位被保留不使用。另外,當(dāng)表項(xiàng)直接映射到頁時(shí),PAT 標(biāo)志位在表項(xiàng)的位置也不相同。當(dāng)表項(xiàng)映射到 4KB 的頁時(shí)(1 級頁表項(xiàng)),PAT 標(biāo)志位在第 7 位,該表項(xiàng)沒有 PS 位;當(dāng)表項(xiàng)映射到 2MB (2 級頁表項(xiàng))或 1 GB (3 級頁表項(xiàng))的頁時(shí),PAT 標(biāo)志位在第 12 位。

各標(biāo)志位說明如下:

  • P 位:位 0,存在(Present)位。指示表項(xiàng)映射的頁或頁表是否存在于內(nèi)存中。當(dāng)該位為 1 時(shí),說明存在;否則,說明不存在。在地址轉(zhuǎn)換過程中,遇到 P 位為 0 的表項(xiàng)會觸發(fā) Page-Fault 異常。
  • R/W 位:位 1,讀寫(Read/Write)位。當(dāng)該位為 0 時(shí),表項(xiàng)所控制的內(nèi)存區(qū)域不允許寫入。
  • U/S 位:位 2,用戶/管理模式(User/Supervisor)位。為 0 時(shí),表示管理模式;否則,表示用戶模式。該位控制著訪問權(quán)限,當(dāng)該位為 0 時(shí),不允許從用戶態(tài)訪問表項(xiàng)控制的內(nèi)存區(qū)域。
  • PWT 位:位 3,頁級直寫( Page-level Write-Through)位。該位間接控制內(nèi)存的緩存類型。
  • PCD 位:位 4,緩存禁止(Page-level Cache Disable)位。該位間接控制內(nèi)存的緩存類型。
  • A 位:位 5,訪問(Accessed)位。指示在線性地址轉(zhuǎn)換過程中是否使用了該表項(xiàng)。
  • D 位:位 6,臟(Dirty)位。指示表項(xiàng)控制的內(nèi)存區(qū)域是否寫入了數(shù)據(jù)。
  • PS 位:位 7,頁大?。≒age Size)位。當(dāng)表項(xiàng)直接映射到頁時(shí),為 1;當(dāng)表項(xiàng)引用了其它頁表時(shí),為 0。頁表項(xiàng)(PTE)沒有 PS 位。
  • G 位:位 8,全局(Global)位。指示頁面的 TLB 是否是全局的。
  • R 位:位 9,重啟(Restart)位。普通分頁忽略該標(biāo)志位,只對 HALT 分頁有效。
  • PAT 位:位 7 或位 12,頁屬性表(Page Attribute Table)位。該位間接控制內(nèi)存的緩存類型。
  • XD 位:位 63,禁止執(zhí)行(eXecute-Disable)位。如果為 1,該表項(xiàng)控制的內(nèi)存區(qū)域不允許指令查詢。

2.2多級頁表的進(jìn)階之路

隨著計(jì)算機(jī)系統(tǒng)的不斷發(fā)展,內(nèi)存容量日益增大,程序?qū)?nèi)存的需求也愈發(fā)復(fù)雜,傳統(tǒng)的單級頁表逐漸暴露出一些局限性。想象一下,在一個(gè) 32 位的系統(tǒng)中,虛擬地址空間高達(dá) 4GB,若以 4KB 為一頁大小進(jìn)行計(jì)算,那么需要的頁表項(xiàng)數(shù)量將多達(dá) 100 多萬個(gè)(2^20)。每個(gè)頁表項(xiàng)占用一定的內(nèi)存空間,如此龐大數(shù)量的頁表項(xiàng),所占用的內(nèi)存開銷將是巨大的,這無疑是一種資源的浪費(fèi),就好比為了管理一個(gè)大型倉庫,準(zhǔn)備了一份極其冗長且大部分區(qū)域?yàn)榭罩玫奈锲非鍐?,耗費(fèi)了大量紙張卻沒有充分發(fā)揮作用。

為了解決這一問題,多級頁表應(yīng)運(yùn)而生,它猶如一套精心設(shè)計(jì)的多層索引系統(tǒng),為大規(guī)模內(nèi)存管理帶來了新的曙光。以常見的二級頁表為例,虛擬地址被劃分為三個(gè)部分:頁目錄索引、頁表索引和頁內(nèi)偏移。最頂層的是頁目錄,它就像是一本總目錄,將整個(gè)虛擬地址空間劃分為若干個(gè)較大的區(qū)域,每個(gè)區(qū)域?qū)?yīng)一個(gè)頁目錄項(xiàng),這些頁目錄項(xiàng)指向第二層的頁表。而第二層的頁表,才真正詳細(xì)記錄著虛擬頁與物理頁框的映射關(guān)系,如同在總目錄下細(xì)分的各個(gè)子目錄,精準(zhǔn)指向具體的物品存放位置。

當(dāng)進(jìn)程訪問一個(gè)虛擬地址時(shí),首先根據(jù)頁目錄索引,在頁目錄中找到對應(yīng)的頁目錄項(xiàng),獲取到指向頁表的指針;接著,依據(jù)頁表索引,在相應(yīng)的頁表中查找具體的頁表項(xiàng),從而得到物理頁框號;最后,結(jié)合頁內(nèi)偏移,就能準(zhǔn)確無誤地定位到物理內(nèi)存中的目標(biāo)數(shù)據(jù)。這種分層的結(jié)構(gòu),使得頁表的存儲變得更加靈活高效。對于那些尚未被使用的虛擬地址區(qū)域,對應(yīng)的二級頁表可以暫不創(chuàng)建,只有當(dāng)進(jìn)程實(shí)際訪問到相關(guān)區(qū)域時(shí),才按需創(chuàng)建頁表,大大減少了內(nèi)存的不必要占用,就像只有當(dāng)需要查看某個(gè)子目錄下的物品時(shí),才去詳細(xì)構(gòu)建該子目錄,避免了一開始就準(zhǔn)備所有可能用到的詳細(xì)清單,節(jié)省了大量的紙張(內(nèi)存)。

在 64 位系統(tǒng)中,甚至?xí)捎酶鄬蛹壍捻摫?,如四級頁表,進(jìn)一步細(xì)化內(nèi)存管理粒度,以適應(yīng)更為龐大的虛擬地址空間需求。多級頁表的出現(xiàn),充分展現(xiàn)了計(jì)算機(jī)系統(tǒng)設(shè)計(jì)的智慧,在滿足內(nèi)存高效管理需求的同時(shí),最大限度地優(yōu)化了資源利用,為現(xiàn)代操作系統(tǒng)的穩(wěn)定高效運(yùn)行提供了堅(jiān)實(shí)保障。

三、虛擬內(nèi)存布局

x86_64 架構(gòu)下,虛擬內(nèi)存中屬于內(nèi)核空間的各內(nèi)存區(qū)域,其起始地址、空間大小、用途都是預(yù)先設(shè)計(jì)好的。4 級分頁下,內(nèi)存布局如下所示:

// file: Documentation/x86/x86_64/mm.txt
 Virtual memory map with 4 level page tables:
 
 0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm
 hole caused by [48:63] sign extension
 ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole
 ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory
 ffffc80000000000 - ffffc8ffffffffff (=40 bits) hole
 ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space
 ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole
 ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)
 ... unused hole ...
 ffffffff80000000 - ffffffffa0000000 (=512 MB)  kernel text mapping, from phys 0
 ffffffffa0000000 - ffffffffff5fffff (=1525 MB) module mapping space
 ffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscalls
 ffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole

其中,地址 0x0000 7FFF FFFF FFFF - 0x0000 7FFF FFFF FFFF 共128T(47位),屬于用戶空間;地址 0xFFFF 8000 0000 0000 - 0xFFFF FFFF FFFF FFFF 共128T(47位), 屬于內(nèi)核空間。示意圖如下:

圖片圖片

這里我們重點(diǎn)關(guān)注下物理內(nèi)存直接映射區(qū)和內(nèi)核代碼映射區(qū)。物理內(nèi)存直接映射區(qū),虛擬地址區(qū)間為 0xFFFF 8800 0000 0000 - 0xFFFF E900 0000 0000, 共 64T 大小。Linux 內(nèi)核會把所有的物理內(nèi)存映射到該虛擬地址區(qū)間。內(nèi)核定義了宏 __PAGE_OFFSET 以及 PAGE_OFFSET,用來表示該區(qū)間的起始地址:

// file: arch/x86/include/asm/page_64_types.h
 #define __PAGE_OFFSET           _AC(0xffff880000000000, UL)
 // file: arch/x86/include/asm/page_types.h
 #define PAGE_OFFSET     ((unsigned long)__PAGE_OFFSET)

該區(qū)間內(nèi)的地址減去 __PAGE_OFFSET,就可以得到對應(yīng)的物理地址。內(nèi)核代碼映射區(qū),虛擬地址區(qū)間為 0xFFFF FFFF 8000 0000 - 0xFFFF FFFF A000 0000,共 512M 大小。該區(qū)域用于映射內(nèi)核代碼段、數(shù)據(jù)段、bss 段等內(nèi)容。內(nèi)核定義了宏 __START_KERNEL_map 來表示該區(qū)間的起始地址:

// file: arch/x86/include/asm/page_64_types.h
 #define __START_KERNEL_map  _AC(0xffffffff80000000, UL)

同理,該區(qū)域內(nèi)的地址減去 __START_KERNEL_map后,就能得到對應(yīng)的物理地址。

四、分頁實(shí)戰(zhàn):內(nèi)存分配與回收藝術(shù)

4.1內(nèi)存分配的精細(xì)策略

在 Linux 內(nèi)核的實(shí)際運(yùn)行過程中,內(nèi)存分配就像是一場精心策劃的資源調(diào)配行動(dòng),每一個(gè)步驟都蘊(yùn)含著智慧與巧思。當(dāng)進(jìn)程向內(nèi)核發(fā)出內(nèi)存請求時(shí),內(nèi)核便依據(jù)既定的規(guī)則,有條不紊地從物理內(nèi)存這片 “資源寶庫” 中選取合適的頁進(jìn)行分配。

內(nèi)核分配內(nèi)存時(shí),通常以頁為基本單位進(jìn)行操作。對于一些小型的數(shù)據(jù)結(jié)構(gòu)或臨時(shí)變量,它們所需的內(nèi)存空間往往遠(yuǎn)小于一頁的大小,此時(shí)內(nèi)核并不會直接分配一整頁,而是采用一種更為精妙的策略 ——slab 分配器。slab 分配器就像是一位精打細(xì)算的管家,它預(yù)先將頁劃分為多個(gè)大小固定的對象池,每個(gè)對象池存放著相同類型、相同大小的對象。當(dāng)需要分配內(nèi)存時(shí),它能快速地從對應(yīng)的對象池中取出一個(gè)空閑對象,就像從裝滿相同規(guī)格零件的盒子里拿出一個(gè)零件一樣便捷高效,大大減少了內(nèi)存碎片化的風(fēng)險(xiǎn),同時(shí)提高了內(nèi)存分配的速度。

而對于那些較大的內(nèi)存需求,比如進(jìn)程加載一個(gè)大型的動(dòng)態(tài)鏈接庫或者運(yùn)行一個(gè)內(nèi)存密集型的應(yīng)用程序,內(nèi)核則會直接分配連續(xù)的多個(gè)頁。這種分配方式就像是為大型項(xiàng)目預(yù)留一整片連續(xù)的場地,確保數(shù)據(jù)的存儲和訪問能夠高效、順暢地進(jìn)行。在內(nèi)核的內(nèi)存分配代碼中,有著嚴(yán)謹(jǐn)?shù)倪壿嬇袛?,它會根?jù)請求內(nèi)存的大小、當(dāng)前內(nèi)存的使用狀況以及系統(tǒng)的性能需求等多方面因素,綜合考量選擇最優(yōu)的分配方案,確保每一頁內(nèi)存都能物盡其用,為系統(tǒng)的穩(wěn)定運(yùn)行提供堅(jiān)實(shí)保障。

4.2內(nèi)存回收的權(quán)衡之道

內(nèi)存回收是內(nèi)存管理中的另一項(xiàng)關(guān)鍵任務(wù),它就像是一場及時(shí)雨,在內(nèi)存資源緊張時(shí)為系統(tǒng)帶來生機(jī)。當(dāng)系統(tǒng)運(yùn)行一段時(shí)間后,隨著進(jìn)程的不斷創(chuàng)建與銷毀,內(nèi)存中的頁面使用情況變得愈發(fā)復(fù)雜,一些頁面可能長時(shí)間未被使用,占用著寶貴的內(nèi)存空間,此時(shí)就需要啟動(dòng)內(nèi)存回收機(jī)制。

內(nèi)存回收的觸發(fā)條件多種多樣。一方面,當(dāng)內(nèi)核檢測到空閑內(nèi)存的數(shù)量低于某個(gè)預(yù)設(shè)的閾值時(shí),就如同水庫水位降至警戒線以下,系統(tǒng)會立即啟動(dòng)內(nèi)存回收程序,確保有足夠的內(nèi)存可供后續(xù)的進(jìn)程使用。這個(gè)閾值的設(shè)定并非一成不變,它會根據(jù)系統(tǒng)的配置、運(yùn)行負(fù)載等因素動(dòng)態(tài)調(diào)整,就像根據(jù)不同季節(jié)、不同用水量靈活調(diào)整水庫的警戒水位一樣,以達(dá)到最佳的資源利用效果。

另一方面,在一些特定的場景下,如系統(tǒng)進(jìn)入休眠狀態(tài)或者進(jìn)行大規(guī)模的內(nèi)存密集型任務(wù)切換時(shí),為了保證系統(tǒng)的平穩(wěn)過渡,也會提前觸發(fā)內(nèi)存回收,釋放不必要的內(nèi)存占用,為關(guān)鍵任務(wù)騰出空間。

在內(nèi)存回收的過程中,頁面置換算法起著核心作用。常見的頁面置換算法有先進(jìn)先出(FIFO)算法、最近最少使用(LRU)算法以及時(shí)鐘(Clock)算法等,它們就像是不同風(fēng)格的 “管家”,各有其獨(dú)特的管理策略。

先進(jìn)先出算法遵循著最樸素的原則,認(rèn)為最先進(jìn)入內(nèi)存的頁面最有可能是最早不再被使用的,就像排隊(duì)時(shí)先到的人先離開一樣,它將內(nèi)存中的頁面按照進(jìn)入的先后順序排成一個(gè)隊(duì)列,當(dāng)需要置換頁面時(shí),總是淘汰隊(duì)首的頁面。然而,這種算法在實(shí)際應(yīng)用中存在一定的局限性,因?yàn)橛行╉撁骐m然最先進(jìn)入內(nèi)存,但可能在后續(xù)的運(yùn)行過程中仍然頻繁被訪問,此時(shí)若按照先進(jìn)先出的原則將其置換出去,容易導(dǎo)致頻繁的頁面調(diào)入調(diào)出,降低系統(tǒng)性能,這種現(xiàn)象被稱為 Belady 異常。

最近最少使用算法則顯得更加 “智能”,它基于一種局部性原理,認(rèn)為如果一個(gè)頁面在過去一段時(shí)間內(nèi)長時(shí)間未被訪問,那么在未來的短期內(nèi)它也不太可能被訪問。所以,LRU 算法會為每個(gè)頁面記錄一個(gè)訪問時(shí)間戳或者使用次數(shù),當(dāng)需要置換頁面時(shí),選擇那個(gè)訪問時(shí)間最久遠(yuǎn)或者使用次數(shù)最少的頁面淘汰出去,就像清理倉庫時(shí)先清理那些長時(shí)間未動(dòng)過的物品一樣。這種算法在大多數(shù)情況下能夠較好地反映頁面的實(shí)際使用情況,減少不必要的頁面置換,提高系統(tǒng)性能,但它需要額外的硬件或軟件開銷來記錄頁面的訪問信息。

時(shí)鐘算法是一種結(jié)合了先進(jìn)先出算法和近似 LRU 算法思想的折衷方案。它將內(nèi)存中的頁面看作是時(shí)鐘表盤上的一個(gè)個(gè)刻度,每個(gè)頁面都有一個(gè)與之對應(yīng)的引用位,就像時(shí)鐘指針走過的刻度會被標(biāo)記一樣。當(dāng)頁面被訪問時(shí),其引用位被置為 1。在進(jìn)行頁面置換時(shí),時(shí)鐘指針從當(dāng)前位置開始順序掃描頁面,遇到引用位為 0 的頁面就將其置換出去,若遇到引用位為 1 的頁面,則先將其引用位清零,然后繼續(xù)掃描,直到找到一個(gè)可置換的頁面為止。這種算法在一定程度上模擬了 LRU 算法的行為,同時(shí)避免了 LRU 算法中記錄精確訪問時(shí)間戳所帶來的高開銷,以相對較低的成本實(shí)現(xiàn)了較為合理的頁面置換策略。

不同的頁面置換算法在不同的應(yīng)用場景下各有優(yōu)劣,Linux 內(nèi)核會根據(jù)系統(tǒng)的實(shí)時(shí)運(yùn)行狀態(tài)、硬件配置以及性能需求等因素,靈活選擇或組合使用這些算法,力求在內(nèi)存回收的過程中達(dá)到最佳的平衡,確保系統(tǒng)能夠在有限的內(nèi)存資源下穩(wěn)定、高效地運(yùn)行。

五、分頁優(yōu)勢盡顯:系統(tǒng)性能飆升的密碼

5.1內(nèi)存利用率的飛躍

分頁機(jī)制猶如一位神奇的魔法師,將原本可能雜亂無章、碎片化嚴(yán)重的內(nèi)存空間,變得井然有序,極大地提升了內(nèi)存的利用率。在未引入分頁之前,內(nèi)存分配常常面臨著內(nèi)碎片和外碎片的困擾。內(nèi)碎片就像是一個(gè)個(gè)藏在角落里難以利用的 “小角落”,當(dāng)程序所需內(nèi)存大小不是分配單元(如分區(qū))的整數(shù)倍時(shí),剩余的那部分空間就白白浪費(fèi)了,如同買了一大盒月餅,最后剩下幾個(gè)零散的小格子裝不滿東西。外碎片則更像是散落在各處的 “拼圖碎片”,隨著程序的頻繁加載與卸載,內(nèi)存中會出現(xiàn)許多不連續(xù)的小空閑塊,當(dāng)有新程序需要一塊較大的連續(xù)內(nèi)存時(shí),盡管空閑內(nèi)存的總量足夠,卻因這些碎片分散各處而無法滿足需求,就像拼圖時(shí)發(fā)現(xiàn)有很多小塊,但就是湊不出一塊完整的大區(qū)域。

分頁機(jī)制的出現(xiàn)徹底改變了這一局面。它將內(nèi)存劃分成固定大小的頁,無論是分配還是回收內(nèi)存,都以頁為基本單位進(jìn)行操作。這就好比把一個(gè)大倉庫分割成規(guī)格統(tǒng)一的小儲物格,每個(gè)儲物格都能被精準(zhǔn)管理和高效利用。當(dāng)程序需要內(nèi)存時(shí),內(nèi)核按照頁的粒度進(jìn)行分配,即使程序大小不是頁大小的整數(shù)倍,浪費(fèi)的空間也僅僅是最后一頁的一小部分,相較于之前的分區(qū)分配方式,內(nèi)碎片的問題得到了有效緩解。而且,由于頁的大小固定,內(nèi)存中空閑頁的分布變得清晰明了,內(nèi)核可以通過一些巧妙的算法(如伙伴系統(tǒng))將相鄰的空閑頁合并成更大的空閑塊,或者快速找到滿足需求的空閑頁組合,使得外碎片問題也迎刃而解,讓內(nèi)存的每一寸 “土地” 都能得到充分開墾。

據(jù)相關(guān)數(shù)據(jù)統(tǒng)計(jì),在一些復(fù)雜的服務(wù)器應(yīng)用場景中,引入分頁機(jī)制后,內(nèi)存利用率相較于傳統(tǒng)的連續(xù)內(nèi)存分配方式提升了 30% - 50%,這意味著系統(tǒng)能夠承載更多的服務(wù)任務(wù),為用戶提供更流暢的體驗(yàn),如同將原本狹窄擁擠的道路拓寬,讓車輛(進(jìn)程)能夠更加順暢地通行。

5.2進(jìn)程隔離的安全護(hù)盾

分頁機(jī)制為進(jìn)程之間構(gòu)建了一道堅(jiān)不可摧的安全護(hù)盾,確保每個(gè)進(jìn)程都能在自己的獨(dú)立 “領(lǐng)地” 內(nèi)安穩(wěn)運(yùn)行,互不干擾,為系統(tǒng)的穩(wěn)定與安全奠定了堅(jiān)實(shí)基礎(chǔ)。

在多進(jìn)程并發(fā)執(zhí)行的操作系統(tǒng)環(huán)境中,如果沒有有效的內(nèi)存隔離機(jī)制,就如同多個(gè)家庭住在一個(gè)沒有墻壁分隔的大房子里,彼此的生活空間完全暴露,極易引發(fā)混亂。一個(gè)進(jìn)程可能會不小心誤讀到另一個(gè)進(jìn)程的數(shù)據(jù),甚至惡意篡改其他進(jìn)程的內(nèi)存內(nèi)容,導(dǎo)致系統(tǒng)崩潰、數(shù)據(jù)丟失等嚴(yán)重后果。

分頁機(jī)制通過為每個(gè)進(jìn)程創(chuàng)建獨(dú)立的頁表,巧妙地解決了這一難題。每個(gè)進(jìn)程都擁有自己的虛擬地址空間,這些虛擬地址通過各自的頁表映射到物理內(nèi)存的不同頁框上,就像每個(gè)家庭都有獨(dú)立的房間布局圖(頁表),依據(jù)這張圖,他們只能進(jìn)入自己家的房間(物理內(nèi)存頁),而無法闖入鄰居家。即使兩個(gè)進(jìn)程在虛擬地址空間中使用了相同的地址,經(jīng)過頁表的轉(zhuǎn)換,它們所對應(yīng)的物理內(nèi)存位置也是截然不同的,如同兩家的房間號可能一樣,但實(shí)際所處的物理位置(樓層、朝向等)卻大相徑庭,從根本上杜絕了進(jìn)程間相互干擾的可能性。

以常見的網(wǎng)絡(luò)服務(wù)器為例,它需要同時(shí)處理來自眾多客戶端的請求,每個(gè)請求都會觸發(fā)一個(gè)獨(dú)立的進(jìn)程進(jìn)行處理。分頁機(jī)制確保了這些進(jìn)程在內(nèi)存層面的獨(dú)立性,即使某個(gè)進(jìn)程因遭受惡意攻擊而出現(xiàn)內(nèi)存異常,也不會波及其他正常運(yùn)行的進(jìn)程,服務(wù)器整體仍能穩(wěn)定地為其他客戶端提供服務(wù),保障了系統(tǒng)的高可用性與安全性,就像一座堅(jiān)固的城堡,各個(gè)房間(進(jìn)程)相互獨(dú)立,即使一間屋子著火(某個(gè)進(jìn)程出錯(cuò)),也不會蔓延到整個(gè)城堡(系統(tǒng)崩潰),為城堡里的居民(其他進(jìn)程)提供了可靠的庇護(hù)。

六、Linux內(nèi)核分頁:持續(xù)進(jìn)化的傳奇

回首分頁機(jī)制的發(fā)展歷程,從早期簡單的應(yīng)對內(nèi)存管理困境,到如今多級頁表、復(fù)雜頁面置換算法等精妙設(shè)計(jì)的呈現(xiàn),它始終緊扣時(shí)代的脈搏,與計(jì)算機(jī)硬件的飛速發(fā)展、軟件應(yīng)用的日益繁雜同頻共振。每一次的升級與優(yōu)化,都像是為 Linux 系統(tǒng)注入了一股新的活力,讓它能夠從容應(yīng)對內(nèi)存管理中的各種挑戰(zhàn)。

在未來,隨著人工智能、大數(shù)據(jù)、云計(jì)算等前沿技術(shù)的持續(xù)突破,Linux 內(nèi)核的分頁機(jī)制必將踏上新的征程?;蛟S,在量子計(jì)算時(shí)代的浪潮下,我們將見證全新的量子分頁算法,以超乎想象的速度處理海量數(shù)據(jù)的內(nèi)存映射;又或是在物聯(lián)網(wǎng)的廣袤天地中,分頁機(jī)制將進(jìn)一步適配微型設(shè)備的超低功耗、小內(nèi)存需求,以極小的資源開銷保障設(shè)備的穩(wěn)定運(yùn)行。

分頁機(jī)制作為 Linux 內(nèi)核內(nèi)存管理的中流砥柱,已然鑄就了無數(shù)輝煌,而它的傳奇故事仍在繼續(xù)書寫,不斷推動(dòng)著 Linux 系統(tǒng)向著更高性能、更強(qiáng)大功能的巔峰奮勇攀登,持續(xù)為全球無數(shù)用戶與開發(fā)者賦能,開啟更為絢爛的科技新篇章。

責(zé)任編輯:武曉燕 來源: 深度Linux
相關(guān)推薦

2025-04-15 06:00:00

2025-01-06 08:00:09

2009-12-17 11:00:47

Linux內(nèi)存管理

2025-03-21 00:00:00

2018-12-06 10:22:54

Linux內(nèi)核內(nèi)存

2025-04-07 04:20:00

Linux操作系統(tǒng)內(nèi)存管理

2023-05-08 08:05:42

內(nèi)核模塊Linux

2018-03-01 16:25:52

Linux內(nèi)核內(nèi)存管理

2018-05-18 09:07:43

Linux內(nèi)核內(nèi)存

2018-12-06 10:40:50

磁盤緩存內(nèi)存

2017-09-04 15:15:48

Linux內(nèi)核內(nèi)存屏障

2021-11-14 07:29:55

Linux 內(nèi)核靜態(tài)追蹤Linux 系統(tǒng)

2021-11-15 04:00:07

Linux 內(nèi)核動(dòng)態(tài)

2021-07-10 08:29:13

Docker內(nèi)核Namespace

2022-03-03 18:18:53

BPF解釋器系統(tǒng)

2015-10-09 10:22:47

分頁內(nèi)存尋址Linux

2013-10-11 17:32:18

Linux運(yùn)維內(nèi)存管理

2011-07-11 18:02:50

java

2011-07-11 18:10:28

java

2024-03-15 08:54:59

Linux內(nèi)核NUMA
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號