1.2 Linux內(nèi)存架構(gòu)
為了執(zhí)行一個(gè)進(jìn)程,Linux內(nèi)核為請(qǐng)求的進(jìn)程分配一部分內(nèi)存區(qū)域。該進(jìn)程使用該內(nèi)存區(qū)域作為其工作區(qū)并執(zhí)行請(qǐng)求的工作。它與你的申請(qǐng)一個(gè)辦公桌,然后使用辦公桌來擺放紙張、文檔和備忘錄來執(zhí)行你的工作類似。不同之處是內(nèi)核必須使用更動(dòng)態(tài)的方式來分配內(nèi)存空間。有時(shí)運(yùn)行的進(jìn)程數(shù)會(huì)達(dá)到數(shù)萬(wàn)個(gè),但內(nèi)存的數(shù)量是有限的。因此,Linux內(nèi)核必須有效地處理內(nèi)存。在本節(jié),我們將會(huì)講述Linux的內(nèi)存結(jié)構(gòu)、地址分布和Linux如何有效地管理內(nèi)存空間。
1.2.1 物理和虛擬內(nèi)存
今天我們已經(jīng)要面對(duì)選擇32位和64位系統(tǒng)的問題。對(duì)于企業(yè)級(jí)客戶的其中一個(gè)最重要的不同是虛擬內(nèi)存的地址是否能超過4GB。從性能的角度來看,理解32位和64位系統(tǒng)中Linux內(nèi)核如何把物理內(nèi)存映射到虛擬內(nèi)核是重要的。
從圖1-10中,可以看出Linux內(nèi)核在處理32位和64位系統(tǒng)內(nèi)存的方式上的明顯的差別。介紹內(nèi)存內(nèi)存到虛擬內(nèi)存的映射細(xì)節(jié)已經(jīng)超出了本文的范圍,所以本文著重介紹Linux內(nèi)存結(jié)構(gòu)的部分細(xì)節(jié)。
在32位的架構(gòu)上,如IA-32,Linux內(nèi)核只能直接訪問物理內(nèi)存的前1GB(當(dāng)考慮部分保留是為896MB)。所謂的 ZONE_NORMAL之上的內(nèi)存必須要被映射到1GB以上的內(nèi)存中。該映射對(duì)于應(yīng)用來說是完全透明的,但是在ZONE_HIGHMEM中申請(qǐng)內(nèi)存頁(yè)會(huì)導(dǎo)致一個(gè)性能的稍微下降。
另一方面,在64位的架構(gòu)上,如x86-64(也叫x64),ZONE_HIGHMEM可以一直延伸到64GB,或者在IA-64系統(tǒng)上可以延伸到128GB。正如你所見到的,通過64位的架構(gòu),內(nèi)存頁(yè)從ZONE_HIGHMEM到ZONE_NORMAL的映射開銷可以被消除。

圖1-10 32位和64位系統(tǒng)的Linux內(nèi)核內(nèi)存布局
虛擬內(nèi)存地址布局
圖1-11展示了32位和64位架構(gòu)的Linux虛擬地址布局。
在32位架構(gòu)上,一個(gè)進(jìn)程能訪問的最大的地址空間為4GB。這是32位虛擬地址的一個(gè)限制。在標(biāo)準(zhǔn)的實(shí)現(xiàn)里,虛擬地址空間被分為3GB的用戶空間和1GB的內(nèi)核空間。這有一點(diǎn)類似于4G/4G尋址布局實(shí)現(xiàn)的變種。
另一方面,在64位架構(gòu)中,如x86-64和IA64,沒有此限制。每個(gè)單獨(dú)進(jìn)程都能得益于于廣闊而巨大的地址空間。

圖1-11 32位和64位架構(gòu)的虛擬內(nèi)存地址布局
1.2.2 虛擬內(nèi)存管理
操作系統(tǒng)的物理內(nèi)存架構(gòu)對(duì)于應(yīng)用和用戶來說通常是不可見的,因?yàn)椴僮飨到y(tǒng)會(huì)把任何的物理內(nèi)存都映射到虛擬內(nèi)存中。如果我們想要理解在Linux操作系統(tǒng)中的調(diào)優(yōu)的可能性,我們必須理解Linux如何處理虛擬內(nèi)存。正如1.2.1中“物理內(nèi)存和虛擬內(nèi)存”的介紹,應(yīng)用并不能申請(qǐng)物理內(nèi)存,但當(dāng)向Linux內(nèi)核請(qǐng)求一定大小的內(nèi)存映射,得到的是一個(gè)虛擬內(nèi)存的映射。如圖1-12所示,虛擬內(nèi)存不一定要映射到物理內(nèi)存中。如果你的應(yīng)用申請(qǐng)了大量的內(nèi)存,這些內(nèi)存中的一部分可能映射到磁盤的swap文件中。
圖1-12展示了,應(yīng)用程序通常直接寫不直接寫磁盤,而是直接寫緩存(cache)或緩沖(buffer)。當(dāng)pdflush內(nèi)核線程空閑或者文件大小超出了緩存緩沖大小時(shí),pdfflush內(nèi)核線程會(huì)將緩存/緩沖的數(shù)據(jù)清空并寫入到磁盤中。參閱“清空臟緩沖”。

圖1-12 Linux虛擬內(nèi)存管理
Linux內(nèi)核處理物理磁盤的寫操作與Linux管理磁盤緩存緊密相連。其他的操作系統(tǒng)只分配部分內(nèi)存作為磁盤緩存,而Linux處理內(nèi)存資源則更加有效。默認(rèn)的虛擬內(nèi)存管理配置分配所有可用的空閑內(nèi)存作為磁盤的緩存。因此在擁有大量?jī)?nèi)存的Linux系統(tǒng)中,經(jīng)??吹街挥?0MB的空閑內(nèi)存。
在相同的情況下,Linux管理swap空間也非常有效率。swap空間被使用時(shí)并不意味著出現(xiàn)內(nèi)存的瓶頸,它恰恰證明了Linux管理系統(tǒng)資源如何的有效。詳見“頁(yè)幀回收”。
頁(yè)幀的分配
一頁(yè)是一組連續(xù)線性的物理內(nèi)存(頁(yè)幀)或虛擬內(nèi)存。Linux內(nèi)核以頁(yè)為單位管理內(nèi)存。一頁(yè)的大小通常為4K字節(jié)。當(dāng)一個(gè)進(jìn)程申請(qǐng)一定數(shù)量的頁(yè)時(shí),如果可用的頁(yè)足夠,Linux內(nèi)核馬上分配給進(jìn)程。否則,內(nèi)存頁(yè)必須從其他一些進(jìn)程或內(nèi)存頁(yè)緩存中獲取。Linux內(nèi)存知道可用的內(nèi)存頁(yè)的數(shù)量及位置。
伙伴系統(tǒng)
Linux內(nèi)核通過一種被稱作伙伴系統(tǒng)的機(jī)制管理空閑頁(yè)?;锇橄到y(tǒng)管理空閑頁(yè)并盡力為分配請(qǐng)求分配頁(yè)。它盡最大努力保持內(nèi)存區(qū)域的連續(xù)。如果不考慮分散的小頁(yè),將會(huì)導(dǎo)致內(nèi)存碎片,并導(dǎo)致在連續(xù)區(qū)域內(nèi)申請(qǐng)一大段的頁(yè)變得困難。它將導(dǎo)致效率低下的內(nèi)存使用和性能下降。
圖1-13說明了伙伴系統(tǒng)如何分配頁(yè)。

圖1-13 伙伴系統(tǒng)
當(dāng)嘗試分配頁(yè)失敗,頁(yè)回收會(huì)被激活。參閱“頁(yè)幀回收”。
你可以通過/proc/buddyinfo查找伙伴系統(tǒng)的信息。詳見“Memory used in a zone”。
頁(yè)幀回收
當(dāng)一個(gè)進(jìn)程請(qǐng)求一定數(shù)量的頁(yè)的映射時(shí),如果頁(yè)不可用,Linux內(nèi)核新的請(qǐng)求嘗試通過釋放某些頁(yè)(先前使用過但現(xiàn)在不再使用,但基于某些原則仍然被標(biāo)記為活動(dòng)狀態(tài)的頁(yè))并分配內(nèi)存給該進(jìn)程。這個(gè)過程被稱為面幀回收。kswapd內(nèi)核線程和try_to_free_page()內(nèi)核函數(shù)被用來負(fù)責(zé)頁(yè)的回收。
kswapd線程通常處于可中斷的睡眠狀態(tài),當(dāng)某一區(qū)域中的自由頁(yè)低于一個(gè)閾值時(shí),kswapd線程會(huì)被伙伴系統(tǒng)調(diào)用。它嘗試基于最近最少使用算法從活動(dòng)頁(yè)中找出候選頁(yè)。最近最少使用的頁(yè)將會(huì)被首先釋放?;顒?dòng)列表和非活動(dòng)列表被用于維護(hù)候選頁(yè)。kswapd掃描部分活動(dòng)列表并檢查頁(yè)的使用情況,把最近沒有使用的頁(yè)放到非活動(dòng)列表中。你可以使用vmstat -a命令查看哪些內(nèi)存是活動(dòng)的和哪些內(nèi)存是非活動(dòng)的。
kswapd也遵循其他原則。頁(yè)的使用主要是為了兩個(gè)用途:頁(yè)緩存和進(jìn)程地址空間。頁(yè)緩存是頁(yè)映射到一個(gè)磁盤文件。屬于一個(gè)進(jìn)程地址空間的頁(yè)(被稱為匿名內(nèi)存,因?yàn)樗鼪]有映射到任何文件,也沒有名字)被用于堆和棧。參閱1.1.8,“進(jìn)程內(nèi)存段”。當(dāng)kswapd回收頁(yè)時(shí),它將會(huì)盡量壓縮頁(yè)緩存而不是把進(jìn)程的頁(yè)page out(或者swap out)。
Page out和swap out:“page out”和“swap out”很多時(shí)候都會(huì)被混淆?!皃age out”是指把頁(yè)(整個(gè)地址空間的一部分)放到swap區(qū),而“swap out”是指把整個(gè)地址空間放到swap區(qū)。但是它們有時(shí)候可以交換使用。
大部分被回收和進(jìn)程地址空間的頁(yè)緩存的回收取決于其使用場(chǎng)景,并將對(duì)性能產(chǎn)生影響。你可以通過使用/proc/sys/vm/swappiness對(duì)該行為進(jìn)行一些控制。
swap(交換區(qū))
如前所述,當(dāng)頁(yè)回收發(fā)生時(shí),在非活動(dòng)列表中屬于該進(jìn)程地址空間的候選頁(yè)將會(huì)被page out。發(fā)生交換本身并不意味著發(fā)生了什么狀況。雖然在其他系統(tǒng)中,swap只不過是萬(wàn)一發(fā)生了主要內(nèi)存的過度分配的一種保障,但是Linux更有效地使用swap空間。如圖1-12所示,虛擬內(nèi)存由物理內(nèi)存和磁盤或者swap分區(qū)共同組成。在Linux的虛擬內(nèi)存管理的實(shí)現(xiàn)中,如果一個(gè)內(nèi)存頁(yè)已經(jīng)被分配,但是在一段時(shí)間內(nèi)都沒有被使用,Linux會(huì)把該內(nèi)存頁(yè)移動(dòng)至swap空間中。
你經(jīng)??梢钥吹饺鏶etty的守護(hù)進(jìn)程,它們通常當(dāng)系統(tǒng)啟動(dòng)時(shí)被啟動(dòng),但幾乎不被使用。釋放頁(yè)所占的珍貴的主內(nèi)存并把它移至交換區(qū)似乎是更加高效的。這正是Linux管理swap的方式,因此當(dāng)你發(fā)現(xiàn)交換區(qū)已經(jīng)使用了50%并不需要驚慌。事實(shí)上,swap空間開始被使用并不意味著內(nèi)存瓶頸;相反地,它證明了Linux如何高效地管理系統(tǒng)資源。
電子發(fā)燒友App






















評(píng)論