在內(nèi)核態(tài)申請(qǐng)內(nèi)存比在用戶態(tài)申請(qǐng)內(nèi)存要更為直接,它沒有采用用戶態(tài)那種延遲分配內(nèi)存技術(shù)。內(nèi)核認(rèn)為一旦有內(nèi)核函數(shù)申請(qǐng)內(nèi)存,那么就必須立刻滿足該申請(qǐng)內(nèi)存的請(qǐng)求,并且這個(gè)請(qǐng)求一定是正確合理的。相反,對(duì)于用戶態(tài)申請(qǐng)內(nèi)存的請(qǐng)求,內(nèi)核總是盡量延后分配物理內(nèi)存,用戶進(jìn)程總是先獲得一個(gè)虛擬內(nèi)存區(qū)的使用權(quán),最終通過缺頁異常獲得一塊真正的物理內(nèi)存。
1.物理內(nèi)存的內(nèi)核映射
IA32架構(gòu)中內(nèi)核虛擬地址空間只有1GB大小(從3GB到4GB),因此可以直接將1GB大小的物理內(nèi)存(即常規(guī)內(nèi)存)映射到內(nèi)核地址空間,但超出1GB大小的物理內(nèi)存(即高端內(nèi)存)就不能映射到內(nèi)核空間。為此,內(nèi)核采取了下面的方法使得內(nèi)核可以使用所有的物理內(nèi)存。
1.高端內(nèi)存不能全部映射到內(nèi)核空間,也就是說這些物理內(nèi)存沒有對(duì)應(yīng)的線性地址。不過,內(nèi)核為每個(gè)物理頁框都分配了對(duì)應(yīng)的頁框描述符,所有的頁框描述符都保存在mem_map數(shù)組中,因此每個(gè)頁框描述符的線性地址都是固定存在的。內(nèi)核此時(shí)可以使用alloc_pages()和alloc_page()來分配高端內(nèi)存,因?yàn)檫@些函數(shù)返回頁框描述符的線性地址。
2.內(nèi)核地址空間的后128MB專門用于映射高端內(nèi)存,否則,沒有線性地址的高端內(nèi)存不能被內(nèi)核所訪問。這些高端內(nèi)存的內(nèi)核映射顯然是暫時(shí)映射的,否則也只能映射128MB的高端內(nèi)存。當(dāng)內(nèi)核需要訪問高端內(nèi)存時(shí)就臨時(shí)在這個(gè)區(qū)域進(jìn)行地址映射,使用完畢之后再用來進(jìn)行其他高端內(nèi)存的映射。
由于要進(jìn)行高端內(nèi)存的內(nèi)核映射,因此直接能夠映射的物理內(nèi)存大小只有896MB,該值保存在high_memory中。內(nèi)核地址空間的線性地址區(qū)間如下圖所示:
從圖中可以看出,內(nèi)核采用了三種機(jī)制將高端內(nèi)存映射到內(nèi)核空間:永久內(nèi)核映射,固定映射和vmalloc機(jī)制。
2.物理內(nèi)存管理機(jī)制
基于物理內(nèi)存在內(nèi)核空間中的映射原理,物理內(nèi)存的管理方式也有所不同。內(nèi)核中物理內(nèi)存的管理機(jī)制主要有伙伴算法,slab高速緩存和vmalloc機(jī)制。其中伙伴算法和slab高速緩存都在物理內(nèi)存映射區(qū)分配物理內(nèi)存,而vmalloc機(jī)制則在高端內(nèi)存映射區(qū)分配物理內(nèi)存。
伙伴算法
伙伴算法負(fù)責(zé)大塊連續(xù)物理內(nèi)存的分配和釋放,以頁框?yàn)榛締挝弧T摍C(jī)制可以避免外部碎片。
per-CPU頁框高速緩存
內(nèi)核經(jīng)常請(qǐng)求和釋放單個(gè)頁框,該緩存包含預(yù)先分配的頁框,用于滿足本地CPU發(fā)出的單一頁框請(qǐng)求。
slab緩存
slab緩存負(fù)責(zé)小塊物理內(nèi)存的分配,并且它也作為高速緩存,主要針對(duì)內(nèi)核中經(jīng)常分配并釋放的對(duì)象。
vmalloc機(jī)制
vmalloc機(jī)制使得內(nèi)核通過連續(xù)的線性地址來訪問非連續(xù)的物理頁框,這樣可以最大限度的使用高端物理內(nèi)存。
3.物理內(nèi)存的分配
內(nèi)核發(fā)出內(nèi)存申請(qǐng)的請(qǐng)求時(shí),根據(jù)內(nèi)核函數(shù)調(diào)用接口將啟用不同的內(nèi)存分配器。
3.1 分區(qū)頁框分配器
分區(qū)頁框分配器 (zoned page frame allocator) ,處理對(duì)連續(xù)頁框的內(nèi)存分配請(qǐng)求。分區(qū)頁框管理器分為兩大部分:前端的管理區(qū)分配器和伙伴系統(tǒng),如下圖:
管理區(qū)分配器負(fù)責(zé)搜索一個(gè)能滿足請(qǐng)求頁框塊大小的管理區(qū)。在每個(gè)管理區(qū)中,具體的頁框分配工作由伙伴系統(tǒng)負(fù)責(zé)。為了達(dá)到更好的系統(tǒng)性能,單個(gè)頁框的申請(qǐng)工作直接通過per-CPU頁框高速緩存完成。
該分配器通過幾個(gè)函數(shù)和宏來請(qǐng)求頁框,它們之間的封裝關(guān)系如下圖所示。
這些函數(shù)和宏將核心的分配函數(shù)__alloc_pages_nodemask()封裝,形成滿足不同分配需求的分配函數(shù)。其中,alloc_pages()系列函數(shù)返回物理內(nèi)存首頁框描述符,__get_free_pages()系列函數(shù)返回內(nèi)存的線性地址。
3.2 slab分配器
slab 分配器最初是為了解決物理內(nèi)存的內(nèi)部碎片而提出的,它將內(nèi)核中常用的數(shù)據(jù)結(jié)構(gòu)看做對(duì)象。slab分配器為每一種對(duì)象建立高速緩存。內(nèi)核對(duì)該對(duì)象的分配和釋放均是在這塊高速緩存中操作。一種對(duì)象的slab分配器結(jié)構(gòu)圖如下:
可以看到每種對(duì)象的高速緩存是由若干個(gè)slab組成,每個(gè)slab是由若干個(gè)頁框組成的。雖然slab分配器可以分配比單個(gè)頁框更小的內(nèi)存塊,但它所需的所有內(nèi)存都是通過伙伴算法分配的。
slab高速緩存分專用緩存和通用緩存。專用緩存是對(duì)特定的對(duì)象,比如為內(nèi)存描述符創(chuàng)建高速緩存。通用緩存則是針對(duì)一般情況,適合分配任意大小的物理內(nèi)存,其接口即為kmalloc()。
3.3 非連續(xù)內(nèi)存區(qū)內(nèi)存的分配
內(nèi)核通過vmalloc()來申請(qǐng)非連續(xù)的物理內(nèi)存,若申請(qǐng)成功,該函數(shù)返回連續(xù)內(nèi)存區(qū)的起始地址,否則,返回NULL。vmalloc()和kmalloc()申請(qǐng)的內(nèi)存有所不同,kmalloc()所申請(qǐng)內(nèi)存的線性地址與物理地址都是連續(xù)的,而vmalloc()所申請(qǐng)的內(nèi)存線性地址連續(xù)而物理地址則是離散的,兩個(gè)地址之間通過內(nèi)核頁表進(jìn)行映射。
vmalloc()的工作方式理解起來很簡(jiǎn)單:
1.尋找一個(gè)新的連續(xù)線性地址空間;
2.依次分配一組非連續(xù)的頁框;
3.為線性地址空間和非連續(xù)頁框建立映射關(guān)系,即修改內(nèi)核頁表;
vmalloc()的內(nèi)存分配原理與用戶態(tài)的內(nèi)存分配相似,都是通過連續(xù)的虛擬內(nèi)存來訪問離散的物理內(nèi)存,并且虛擬地址和物理地址之間是通過頁表進(jìn)行連接的,通過這種方式可以有效的使用物理內(nèi)存。但是應(yīng)該注意的是,vmalloc()申請(qǐng)物理內(nèi)存時(shí)是立即分配的,因?yàn)閮?nèi)核認(rèn)為這種內(nèi)存分配請(qǐng)求是正當(dāng)而且緊急的;相反,用戶態(tài)有內(nèi)存請(qǐng)求時(shí),內(nèi)核總是盡可能的延后,畢竟用戶態(tài)跟內(nèi)核態(tài)不在一個(gè)特權(quán)級(jí)。
-
Linux
+關(guān)注
關(guān)注
87文章
11345瀏覽量
210403 -
內(nèi)存
+關(guān)注
關(guān)注
8文章
3055瀏覽量
74334
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
Linux服務(wù)器卡頓救星之一招釋放Cache內(nèi)存
虛擬內(nèi)存和云計(jì)算的關(guān)系
虛擬內(nèi)存溢出該怎么處理 虛擬內(nèi)存在服務(wù)器中的應(yīng)用
Linux下如何管理虛擬內(nèi)存 使用虛擬內(nèi)存時(shí)的常見問題
什么是虛擬內(nèi)存分頁 Windows系統(tǒng)虛擬內(nèi)存優(yōu)化方法
虛擬內(nèi)存不足如何解決 虛擬內(nèi)存和物理內(nèi)存的區(qū)別
虛擬內(nèi)存的作用和原理 如何調(diào)整虛擬內(nèi)存設(shè)置
Linux內(nèi)存泄露案例分析和內(nèi)存管理分享
![<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)存</b>泄露案例分析和<b class='flag-5'>內(nèi)存</b>管理分享](https://file1.elecfans.com//web2/M00/0B/0B/wKgaomcaAfmARLxeAABRvgTXMno355.png)
邏輯內(nèi)存和物理內(nèi)存的區(qū)別
buffers內(nèi)存與cached內(nèi)存的區(qū)別
![buffers<b class='flag-5'>內(nèi)存</b>與cached<b class='flag-5'>內(nèi)存</b>的區(qū)別](https://file1.elecfans.com/web2/M00/FF/1A/wKgZomanNIuASl6xAAAMHRvl4Pc311.png)
物理內(nèi)存模型的演變
Linux內(nèi)核內(nèi)存管理之內(nèi)核非連續(xù)物理內(nèi)存分配
![<b class='flag-5'>Linux</b>內(nèi)核<b class='flag-5'>內(nèi)存</b>管理之內(nèi)核非連續(xù)<b class='flag-5'>物理</b><b class='flag-5'>內(nèi)存</b>分配](https://file1.elecfans.com/web2/M00/C1/9D/wKgaomXX-KCADAsrAAAaZXMwKKg445.png)
評(píng)論