溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Linux中使用全局框架怎么實現(xiàn)內(nèi)存管理

發(fā)布時間:2021-06-12 17:26:46 來源:億速云 閱讀:143 作者:Leah 欄目:系統(tǒng)運維

Linux中使用全局框架怎么實現(xiàn)內(nèi)存管理,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

一.  地址劃分。

1. CPU地址。

CPU地址是指CPU的地址總線能尋址的范圍,32bit-CPU尋址范圍為4G, 這個地址是虛擬的,實際上外部物理內(nèi)存是不會使用這么大的內(nèi)存。

CPU虛擬地址的4G空間,通常劃分為兩部分,一部分為內(nèi)核虛擬地址,通常為3G-4G之間,另一部分為用戶虛擬地址,通常為0G-3G之間,顯然,用戶進程能使用的虛擬地址范圍遠大于內(nèi)核可以使用的虛擬地址空間,但是,物理內(nèi)存只有局限性的幾M,幾G,內(nèi)核虛擬地址如何使用物理內(nèi)存,用戶空間如何使用物理內(nèi)存,這些問題正是linux內(nèi)存管理的關(guān)鍵。

2.  物理內(nèi)存

物理內(nèi)存是指外部存儲數(shù)據(jù)的設(shè)備,有可以被CPU尋址到的地址總線,受到CPU的Cache 和TLB/MMU管理尋址。

需要澄清一個概念:任何代碼是在CPU上運行的,而不是在物理內(nèi)存上,物理內(nèi)存是個設(shè)備,用于存放用戶進程空間的可執(zhí)行代碼或者內(nèi)核關(guān)鍵數(shù)據(jù)結(jié)構(gòu),這些代碼或結(jié)構(gòu)終將是要受到CPU通過MMU尋址,Cache***指令數(shù)據(jù)來獲取的。

NUMA的全稱是非一致性內(nèi)存訪問,它通常是多核訪問的概念,每一個CPU核都會有一個節(jié)點對應(yīng)使用一部分物理內(nèi)存,對這些節(jié)點的管理附加這些數(shù)據(jù)結(jié)構(gòu):perCPU變量,list表串聯(lián)各節(jié)點遍歷,zone的劃分,zonelist的管理等等。為了使問題更加簡單化,我們只分析UMA的一個節(jié)點的情況,當(dāng)然它也包含NUMA的一些數(shù)據(jù)結(jié)構(gòu)特征,這個后面會有所簡述。

下圖是NUMA的一個簡略圖抽象如圖2-1所示。

Linux中使用全局框架怎么實現(xiàn)內(nèi)存管理

      圖2-1 NUMA多核物理內(nèi)存zone示意圖

3.  內(nèi)核虛擬地址空間劃分。

如果讀者僅僅了解一些皮毛,必然認為內(nèi)核的虛擬地址空間僅有邏輯地址這一說,其實這只是內(nèi)存內(nèi)核虛擬地址劃分的一個特例,并非全部的完整表述,現(xiàn)在我劃出完整的圖形,并且改變改變對內(nèi)核虛擬地址空間名稱的叫法,如圖2-2

Linux中使用全局框架怎么實現(xiàn)內(nèi)存管理

圖2-2 內(nèi)核虛擬地址空間劃分及其對物理內(nèi)存的映射

下面來改改名字咯,直接映射的地址我們可以叫為內(nèi)核物理直接映射地址或者邏輯地址。linux原則上只能使用虛擬空間1G中的896M,剩下的128M留作它用,所以直接映射之外的物理內(nèi)存稱為高端內(nèi)存。128M之間的空間又劃分為多個gap安全間隙,虛擬地址,固定映射和持久映射,注意這里的虛擬地址叫法通常和前述的內(nèi)核虛擬地址有些混雜,后者是指CPU內(nèi)核虛擬地址,是更廣的概念。由于直接映射的部分有了名字叫邏輯地址,那么這里的虛擬地址空間常專指這個部分。

虛擬地址有以下用途,使用vm_struct結(jié)構(gòu)體經(jīng)內(nèi)核管理高端內(nèi)存,它可以使用kmap方式獲取高端物理內(nèi)存的空間;也可以不映射物理高端內(nèi)存,將這段地址直接作為外部物理設(shè)備的ioremap地址,從而可以直接操縱設(shè)備,當(dāng)然這也將外部設(shè)備地址空間暴露出來并且容易造成干擾,所以通常不能直接訪問ioremap映射的地址而是用readb/writeb讀寫,而且要做好優(yōu)化屏障設(shè)置并且用iounmap釋放,因為映射了的設(shè)備常具有’邊際效應(yīng)’.

如果沒有高端內(nèi)存,(當(dāng)然32bit的嵌入式系統(tǒng)通常不會使用高端內(nèi)存,至少我見過的那么多關(guān)于ARM,powerPC,MIPS32的嵌入式應(yīng)用都是沒有使用高端內(nèi)存的), 那么固定映射和持久映射也多半不會用到。固定映射可以指定長期持有物理內(nèi)存某些地址頁的占用,這個映射關(guān)系可以在初始階段進行配置,而持久映射在啟用時就建立了同高端內(nèi)存物理頁的映射關(guān)系,它在其他階段都不會被解除。

強調(diào)的是,我這里不關(guān)心高端內(nèi)存,內(nèi)核的直接映射邏輯地址就可以涵蓋全部物理內(nèi)存。

4.  用戶虛擬地址空間的劃分

用戶虛擬地址空間圖構(gòu)并不復(fù)雜,復(fù)雜的是它在虛擬內(nèi)存空間中的應(yīng)用,如何映射文件,如何組織區(qū)間映射,關(guān)聯(lián)的進程是誰,對應(yīng)的內(nèi)存結(jié)構(gòu)體實例是什么等等問題才是用戶虛擬映射最難的地方,下面僅僅劃出圖示,對用戶虛擬內(nèi)存空間可以先有一個大了解,如圖2-3。

Linux中使用全局框架怎么實現(xiàn)內(nèi)存管理

圖2-3用戶空間虛擬內(nèi)存布局

既然用戶空間是虛擬的,那么它是怎么訪問物理內(nèi)存的呢,當(dāng)然就是PGD,PUD,PMD,PTE,OFFSET及其TLB快表查詢了,上層目錄入口PUD和中間目錄入口一般不考慮,考慮二級目錄就可以了。從網(wǎng)上摘的圖2-4:

Linux中使用全局框架怎么實現(xiàn)內(nèi)存管理

圖2-4 用戶進程空間訪問物理內(nèi)存的方法

二.  伙伴系統(tǒng)

伙伴系統(tǒng)是按階管理外界物理內(nèi)存的方法,***有11階,每一階有一個或者多個頁合并的集合并使用指針串聯(lián)起來,同時在同一階中的一個或多個頁集合中形成各自的伙伴,要強調(diào)的是各個階的伙伴都是等頁個數(shù)的,用下圖2-5是比較好理解的。

Linux中使用全局框架怎么實現(xiàn)內(nèi)存管理            

圖2-5 伙伴系統(tǒng)在內(nèi)存中的大致模型

當(dāng)內(nèi)核申請一段按頁卻并非按照階數(shù)分配的內(nèi)存時候,通常會使用伙伴系統(tǒng)原理將其按照該申請空間的***階數(shù)分配,多出來的頁按照伙伴系統(tǒng)算法歸并到其他階的鏈表當(dāng)中形成其他階的新伙伴。釋放該內(nèi)存空間的時候,釋放的空間會嘗試找到能以它為伙伴的那個階進行連接,如果大小超過,則劈開,多余的再尋找其他可以以它為伙伴的階。夠拗口的,但還是很容易理解的,后面會有源代碼呈現(xiàn)出來以實例詳細分析。

三.  反碎片技術(shù):

反碎片機制其實還在伙伴系統(tǒng)之前,它主要是將各個zone區(qū)域的物理內(nèi)存分成可回收reclaimable但不可移動unmovable,可移動movable,不可移動unmovable. 這些標(biāo)記按照一定得list串聯(lián)起來管理,當(dāng)外部條件申請物理內(nèi)存導(dǎo)致許多碎片的時候,它可以按照這些數(shù)據(jù)結(jié)構(gòu)的標(biāo)志,來從新組織歸類物理內(nèi)存,從而減少碎片頁或者孤獨頁。反碎片技術(shù)在嵌入式系統(tǒng)當(dāng)中少用,絕大部分由伙伴系統(tǒng)占據(jù)江山了,因此不會對此做具體分析,簡略過之。

四.    Slab分配機制。

眾所周知,操作系統(tǒng)使用伙伴系統(tǒng)管理內(nèi)存,不僅會造成大量的內(nèi)存碎片,同時處理效率也較低下。SLAB是一種內(nèi)存管理機制,其擁有較高的處理效率,同時也有效的避免內(nèi)存碎片的產(chǎn)生,其核心思想是預(yù)分配。其按照SIZE對內(nèi)存進行分類管理的,當(dāng)申請一塊大小為SIZE的內(nèi)存時,分配器就從SIZE集合中分配一個內(nèi)存塊(BLOCK)出去,當(dāng)釋放一個大小為SIZE的內(nèi)存時,則將該內(nèi)存塊放回到原有集合,而不是釋放給操作系統(tǒng)。當(dāng)又要申請相同大小的內(nèi)存時,可以復(fù)用之前被回收的內(nèi)存塊(BLOCK),從而避免了內(nèi)存碎片的產(chǎn)生。[注:因SLAB處理過程的細節(jié)較多,在此只是做一個原理上的講解

1. 總體結(jié)構(gòu)

Linux中使用全局框架怎么實現(xiàn)內(nèi)存管理

  圖1 SLAB內(nèi)存結(jié)構(gòu)

2.處理流程

如圖1中所示:SLAB管理機制將內(nèi)存大體上分為SLAB頭、SLOT數(shù)組、PAGES數(shù)組、可分配空間、被浪費空間等模塊進行分別管理,其中各模塊的功能和作用:

SLAB頭:包含SLAB管理的匯總信息,如最小分配單元(min_size)、最小分配單元對應(yīng)的位移(min_shift)、頁數(shù)組地址(pages)、空閑頁鏈表(free)、可分配空間的起始地址(start)、內(nèi)存塊結(jié)束地址(end)等等信息(如代碼1所示),在內(nèi)存的管理過程中,內(nèi)存的分配、回收、定位等等操作都依賴于這些數(shù)據(jù)。

SLOT數(shù)組:SLOT數(shù)組各成員分別負責(zé)固定大小的內(nèi)存塊(BLOCK)的分配和回收。在nginx中SLOT[0]~SLOT[7]分別負責(zé)區(qū)間在[1~8]、[9~16]、[17~32]、[33~64]、[65~128]、[129~256]、[257~512]、[513~1024]字節(jié)大小內(nèi)存的分配,但為方便內(nèi)存塊(BLOCK)的分配和回收,每個內(nèi)存塊(BLOCK)的大小為各區(qū)間的上限(8、16、32、64、128、256、512、1024)。比如說:假如應(yīng)用進程請求申請5個字節(jié)的空間,因5處在[1~8]的區(qū)間內(nèi),因此由SLOT[0]負責(zé)該內(nèi)存的分配,但區(qū)間[1~8]的上限為8,因此即使申請5個字節(jié),卻依然分配8字節(jié)給應(yīng)用進程。以此類推:假如申請12字節(jié),12處于區(qū)間[9~16]之間,取上限16,因此由SLOT[1]分配16個字節(jié)給應(yīng)用進程;假如申請50字節(jié),50處于區(qū)間[33~64]之間,取上限64,因此由SLOT[2]分配64個字節(jié)給應(yīng)用進程;假如申請84字節(jié),84處于區(qū)間[65~128]之間,取上限128,因此由SLOT[3]分配128個字節(jié);...;假如申請722字節(jié),722處于區(qū)間[513~1024]之間,取上限1024,因此由SLOT[7]分配1024字節(jié)。

PAGES數(shù)組:PAGES數(shù)組各成員分別負責(zé)可分配空間中各頁的查詢、分配和回收,其處理流程可參考3.2節(jié)的說明。

可分配空間:SLAB在邏輯上將可分配空間劃分成M個內(nèi)存頁,每頁大小為4K。每頁內(nèi)存與PAGES數(shù)組成員一一對應(yīng),由PAGES數(shù)組各成員負責(zé)各內(nèi)存頁的分配和回收。

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI