資源描述:
《linux內(nèi)核之內(nèi)存管理》由會員上傳分享,免費在線閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫。
1、Linux內(nèi)核之內(nèi)存管理作者:harveywang郵箱:harvey.perfect@gmail.com新浪博客地址:http://blog.sina.com.cn/harveyperfect,有關(guān)于減肥和學(xué)習(xí)英語相關(guān)的博文,歡迎交流把linux內(nèi)存管理分為下面四個層面(一)硬件輔助的虛實地址轉(zhuǎn)換(二)內(nèi)核管理的內(nèi)存相關(guān)(三)單個進程的內(nèi)存管理(四)malloc軟件(一)處理器硬件輔助的虛實地址轉(zhuǎn)換(以x86為例)在x86中虛實地址轉(zhuǎn)換分為段式轉(zhuǎn)換和頁轉(zhuǎn)換。段轉(zhuǎn)換過程是由邏輯地址(或稱為虛擬地址)轉(zhuǎn)換為線性地址;頁轉(zhuǎn)換過程則是將線性地址轉(zhuǎn)換為物理地址。段轉(zhuǎn)換示意圖如下X86支持兩
2、種段,gdt和ldt(全局描述段表和局部描述符段表),在linux中只使用了4個全局描述符表,內(nèi)核空間和用戶空間分別兩個gdt,分別對應(yīng)各自的代碼段和數(shù)據(jù)段。也可以認為在linux中變相地disable了x86的段式轉(zhuǎn)換功能。頁轉(zhuǎn)換示意圖如下在linux中x86的cr3寄存器(頁表基地址寄存器)保存在進程的上下文中,在進程切換時會保存或回復(fù)該寄存器的內(nèi)容,這樣每個進程都有自己的轉(zhuǎn)換頁表,從而保證了每個進程有自己的虛擬空間。(一)內(nèi)核管理的內(nèi)存相關(guān)從幾個概念展開內(nèi)存管理:node、zone、buddy、slab1、NodeSGIAltix3000系統(tǒng)的兩個結(jié)點如上圖,NUMA系統(tǒng)的
3、結(jié)點通常是由一組CPU(如,SGIAltix3000是2個Itanium2CPU)和本地內(nèi)存組成。由于每個結(jié)點都有自己的本地內(nèi)存,因此全系統(tǒng)的內(nèi)存在物理上是分布的,每個結(jié)點訪問本地內(nèi)存和訪問其它結(jié)點的遠地內(nèi)存的延遲是不同的,為了優(yōu)化對NUMA系統(tǒng)的支持,引進了Node來將NUMA物理內(nèi)存進行劃分為不同的Node。而操作系統(tǒng)也必須能感知硬件的拓撲結(jié)構(gòu),優(yōu)化系統(tǒng)的訪存。但是Intelx86系統(tǒng)不是NUMA系統(tǒng)。為了保持代碼的一致性,在x86平臺上,Linux將所有物理內(nèi)存都劃分到同一個Node。事實上,對于非NUMA體系結(jié)構(gòu),也是如此處理的。Linux系統(tǒng)用定義了數(shù)組pg_data_
4、tnode_data[MAX_NUMNODES]來管理各個node。2、ZoneLinux中Node、Zone和頁的關(guān)系每個結(jié)點的內(nèi)存被分為多個塊,稱為zones,它表示內(nèi)存中一段區(qū)域。一個zone用structzone結(jié)構(gòu)描述,zone的類型主要有ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM。ZONE_DMA位于低端的內(nèi)存空間,用于某些舊的ISA設(shè)備。ZONE_NORMAL的內(nèi)存直接映射到Linux內(nèi)核線性地址空間的高端部分,ZONE_HIGHMEM位于物理地址高于896MB的區(qū)域。例如,在X86中,zone的物理地址如下:內(nèi)核空間只有1GB線性地址,如果
5、使用大于1GB的物理內(nèi)存就沒法直接映射到內(nèi)核線性空間了。當(dāng)系統(tǒng)中的內(nèi)存大于896MB時,把內(nèi)核線性空間分為兩部分,內(nèi)核中低于896MB線性地址空間直接映射到低896MB的物理地址空間;高于896MB的128MB內(nèi)核線性空間用于動態(tài)映射ZONE_HIGHMEM內(nèi)存區(qū)域(即物理地址高于896MB的物理空間)。3、Buddy如上圖所示,每個zone區(qū)域都采用伙伴系統(tǒng)(buddysystem)來管理空閑內(nèi)存頁面。把所有的空閑頁框分組為11個塊鏈表,每個塊鏈表分別包含大小為1,2,4,8,16,32,64,128,256,512和1024個連續(xù)的頁框。鏈表編號分別為0,1,2,3,…k…1
6、0。從buddysystem中申請頁面過程:1、根據(jù)申請存儲區(qū)域大小查找對應(yīng)的編號為K的塊鏈表。2、如果編號K的鏈表為空,則向編號為k+1的鏈表申請一個存儲區(qū)域。如果編號為k+1鏈表不為空,系統(tǒng)從編號為k+1的鏈表上拆下一個區(qū)域,并將拆下的區(qū)域分為兩個2^k的區(qū)域,一個返還給申請者,另一個則掛到編號為k的鏈表。3、如果編號為k+1的鏈表也為空,編號為k+2的鏈表不為空。則從k+2的鏈表中拆下一個區(qū)域變?yōu)閮蓚€2^(k+1)區(qū)域,一個掛到編號為k+1的鏈表上,把另一個拆為兩個2^k的區(qū)域,一個返還給申請者,把另一個掛到編號為k的鏈表上。4、如果k+2的鏈表也為空,則一直向上迭代,直到
7、編號為10的鏈表為止,如果編號為10的鏈表還為空,則申請失敗。向buddysystem中釋放頁面過程:在向buddysystem釋放頁面時,總會檢測釋放的頁面和鏈表中其他頁面是否可以組成一個更大一級的頁面,如果可以組成,則把這兩個區(qū)域組成一個并掛到更高一級的鏈表中。這個過程是迭代的,釋放過程會一層層向上找伙伴,然后合并成更大的,再向上找伙伴,實在找不到了就停止了!疑問:按照上面的說法,是否會出現(xiàn)這種情況,在釋放某個頁面導(dǎo)致所有頁面都組成了標(biāo)號為10的連續(xù)頁面了。等到再需要分配1個