linux內存管理


一 為什么需要使用虛擬內存

    大家都知道,進程需要使用的代碼和數據都放在內存中,比放在外存中要快很多。問題是內存空間太小了,不能滿足進程的需求,而且現在都是多進程,情況更加糟糕。所以提出了虛擬內存,使得每個進程用於3G的獨立用戶內存空間和共享的1G內核內存空間。(每個進程都有自己的頁表,才使得3G用戶空間的獨立)這樣進程運行的速度必然很快了。而且虛擬內存機制還解決了內存碎片和內存不連續的問題。為什么可以在有限的物理內存上達到這樣的效果呢?

二 虛擬內存的實現機制

    首先呢,提一個概念,交換空間(swap space),這個大家應該不陌生,在重裝系統的時候,會讓你選擇磁盤分區,就比如說一個硬盤分幾個部分去管理。其中就會分一部分磁盤空間用作交換,叫做swap space。其實就是一段臨時存儲空間,內存不夠用的時候就用它了,雖然它也在磁盤中,但省去了很多的查找時間啊。當發生進程切換的時候,內存與交換空間就要發生數據交換一滿足需求。所以啊,進程的切換消耗是很大的,這也說明了為什么自旋鎖比信號量效率高的原因。

    那么我們的程序里申請的內存的時候,linux內核其實只分配一個虛擬內存( 線性地址),並沒有分配實際的物理內存。只有當程序真正使用這塊內存時,才會分配物理內存。這就叫做延遲分配和請頁機制。釋放內存時,先釋放線性區對應的物理內存,然后釋放線性區;"請頁機制"將物理內存的分配延后了,這樣是充分利用了程序的局部性原來,節約內存空間,提高系統吞吐;就是說一個函數可能只在物理內存中呆了一會,用完了就被清除出去了,雖然在虛擬地址空間還在。(不過虛擬地址空間不是事實上的存儲,所以只能說這個函數占據了一段虛擬地址空間,當你訪問這段地址時,就會產生缺頁處理,從交換區把對應的代碼搬到物理內存上來)

三 物理內存與虛擬內存的布局

左邊是物理地址分配,與實際的CPU相關。4KB的這些都是一些控制器所占有,比如lcdc sd卡,他們的寄存器地址就是這樣定死的。但是呢,我們要訪問這些寄存器的時候,還是不能直接用,要使用內存管理的規則,使用虛擬地址去訪問它,所以在驅動等內核程序中需要使用虛擬地址訪問寄存器。如果有人直接使用物理地址訪問寄存器,那么唯一的解釋就是沒有開mmu。不過這樣你的進程就沒有4G內存可以用了。

物理地址分布:

這是偷的別人的圖啦,物理地址有896M直接映射到虛擬地址的內存空間,這是一一對應的映射,只有起始地址不一樣,偏移是一樣的。這個大小大多是固定的,哪怕你的內存超過一個G,太小了就另外說了。注意:用戶區的代碼也是放在這段物理地址里面的,就是說物理地址可以進行二次映射。但不管怎么樣,這段物理地址都是受內核管理。當你內存很大的時候,超過896M時,剩余的那些內存怎么辦呢?這多出來的叫做高端內存,如果你使用vmalloc申請空間,就會在高端內存中分配,如果你使用kmalloc申請空間,就會在小於896的內存中分配。所以還是很講究的啊!!如果你的程序需要使用高端內存,就要調用內核API來分配,所以高端內存並不是想用就能用的哦。不過通過系統把一些應用常住在高端內存到是個好注意。不過前提是你的內存灰常大啊。

為什么要這樣做呢?先看看這里面放些什么?

虛擬地址分布:

關於0-3G用戶空間內存的分布:

談到段式分布,就要說說邏輯地址,線性地址與物理地址的關系:

linux通過段機制把邏輯地址轉換為虛擬地址(就是線性地址),再通過頁機制把虛擬地址轉換為物理地址。所謂分段就是基址不同,偏移一樣,比如說32位,一般程序里面都不會使用這么多的位,可以把前12位用作基址,后20位用作偏移,這樣在特定段就可以只使用偏移尋址了。尋址很方便,不過linux頁基址做的更好。

最后呢再說幾個點:

1 線性地址空間:指linux系統中的虛擬地址空間。

2 cpu尋址是屬於物理地址。所以在使用cpu尋址前要把地址轉換好。

3 物理內存中的高端內存是DDR減去896M后多出來的那一段。虛擬地址里面的高端內存是指用於映射高端內存的虛擬地址空間。不過高端內存被映射到用戶空間,那就是另外一回事了吧。

4 內核空間是可以訪問用戶空間的,級別高就是好啊。不過不是通過虛擬地址直接訪問的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM