Linux是如何管理記憶體的

2022-07-05 03:09:09 字數 2758 閱讀 4219

物理記憶體的管理

linux管理物理記憶體是使用分頁機制實現的。為了使分頁機制在32位和64位體系結構下高效工作,linux採用了乙個四級分頁策略

linux支援多種記憶體分配機制。分配物理記憶體頁框的主要機制是頁面分配器,它使用了著名的夥伴演算法作為物理記憶體分配機制。

管理一塊記憶體的基本思想如下。剛開始,記憶體由一塊連續的片段組成,下圖的簡單例子是64個頁面。當乙個記憶體請求到達時,首先向上捨入到2的冪,比如8個頁面。然後整個記憶體被分割成兩半,如圖b所示。因為這些片段還是太大了,較低的片段被再次二分(c),然後再二分(d)。現在我們有一塊大小合適的記憶體,因此把它分配給請求者,如圖d所示。

現在假定8個頁面的第二個請求到達了。這個請求有(e)直接滿足了。此時4個頁面的第三個請求到達了。最小可用的塊被分割(f),然後其一半被分配(g)。接下來,8頁面裡的第二個塊碑釋放(h)。最後,8頁面的另乙個塊也被釋放。因為剛剛釋放的兩個鄰接的8頁面塊來自同乙個16頁面塊,它們合併起來得到乙個16頁面的塊(i)。

虛擬位址空間

linux為每個程序維持乙個單獨的虛擬位址空間。如下圖所示。

虛擬位址空間被分割成同構連續頁面對齊的區域。也就是說,每個區域由一系列連續的具有相同保護和分頁屬性的頁面組成。**段、資料段、堆、共享庫段以及使用者棧都是不同的區域。每個存在的虛擬頁面都儲存在某個區域中,而不屬於某個區域的虛擬也是不存在的。在虛擬位址空間的區之間可以有空隙。所有對這些空隙的引用都會導致乙個嚴重的頁面故障。

在核心中,每個區是用vm_area_struct項來描述的。乙個程序的所有vm_area_struct用乙個鍊錶連線在一起,並且按照虛擬位址排序以便可以找到所有的頁面。當這個鍊錶太長時(多於32項),就建立乙個樹來加速搜尋。vm_area_struct項列出了該區的屬性。這些屬性包括:保護模式(如,唯讀或者可讀可寫),是否固定在記憶體中(不可換出)、朝向哪個方向生長(資料段向上,棧段向下)。

vm_area_struct也記錄了該區是私有的還是跟乙個或多個其他程序共享的。fork之後,linux為子程序複製乙份區鍊錶,但是為了讓父子程序指向相同的也表。區標記為可讀可寫,但是頁面卻被標記為唯讀。如果任何乙個程序試圖寫頁面,就會產生乙個保護故障,此時核心發現該記憶體區域邏輯上是可寫的,但是頁面卻不是,因此它把該頁面的乙個副本給當前程序同時標記為可讀可寫。這個機制就說明了寫時複製是如何實現的。

vm_area_struct也記錄了該區是否在磁碟上有備份儲存,如果有,在什麼地方。**段把可執行二進位制檔案作為備份儲存,記憶體對映檔案把磁碟檔案作為備份儲存。其他區,如棧,直到它們不得不被換出,否則沒有備份儲存被分配。

乙個頂層記憶體描述符mm_struct收集屬於乙個位址空間的所有虛擬記憶體區相關的資訊,還有關於不同段(**、資料、棧)和使用者共享位址空間的資訊等。乙個位址空間的所有vm_area_struct元素可以通過記憶體描述符用兩種方式訪問。首先,它們是按照虛擬位址順序組織在鍊錶中的。這種方式的有用之處是:當所有的虛擬位址區需要被訪問時,或者當核心查詢分配乙個指定大小的虛擬記憶體區域時。此外,vm_area_struct專案被組織成二叉「紅黑」樹。這種方法用於訪問乙個指定的虛擬記憶體位址。為了能夠用這兩種方法訪問程序位址空間的元素,linux為每個程序使用了更多的狀態,但是卻允許不同的核心操作來使用這些訪問狀態,這對程序而言更加高效。

下圖強調了記錄乙個程序中虛擬儲存器區域的核心資料結構。核心為系統中的每個程序維護乙個單獨的任務結構(源**中的task_struct)。任務結構中的元素包含或者指向核心執行該程序所需要的所有資訊(例如,pid,指向使用者棧的指標、可執行目標檔案的名字以及程式計數器)。

task_struct中的乙個條目指向mm_struct,它描述了虛擬儲存器的當前狀態。我們感興趣的兩個欄位是pdg和mmap,其中pdf指向第一級頁表(頁全域性目錄)的基址,而mmap指向乙個vm_area_struct(區域結構鍊錶),其中每個vm_area_strcuts都描述了當前虛擬位址空間的乙個區域(area)。當核心執行這個程序時,它就將pdf存放在cr3控制暫存器中。

為了我們的目的,乙個具體區域的區域結構包含下面的字段:

vm_struct:指向這個區域的起始處。

vm_end: 指向這個區域的結束處。

vm_prot: 描述這個區域內包含的所有頁的讀寫許可許可權。

vm_flags:描述這個區域內的頁面是與其他程序共享的,還是這個程序私有的、

vm_next: 指向鍊錶中下乙個區域結構。

虛擬位址空間到實體地址空間的對映

虛擬儲存的實現需要依靠硬體的支援,對於不同的cpu來說是不同的。但是幾乎所有的硬體都採用乙個mmu((memmory management unit)的部件來進行對映,如下圖所示。

在頁對映模式下,cpu發出的是virtual address, 即我們的程式看到的是虛擬位址。經過mmu轉換以後就變成了physical address。一般mmu都整合在cpu內部了,不會以獨立的部件存在。

Windows下的記憶體是如何管理的?

參考資料 1 有三種方法 虛擬記憶體,記憶體對映檔案,記憶體堆疊。虛擬記憶體是將頁檔案載入到記憶體,適用於比較大的物件或結構 記憶體對映檔案是將磁碟上檔案載入到記憶體,適用於大檔案和單機的程序間記憶體共享 堆疊就是動態的分配記憶體,適用於小物件的建立。這些在windows核心程式設計中都描述得很詳細...

記憶體管理那些事兒 指標引數是如何傳遞記憶體的

01.如果函式的引數是乙個指標,不要指望用該指標去申請動態記憶體void getmemory char p int main 執行上面的 則會出錯。編譯器總是要為函式的每個引數製作臨時副本,指標 引數p 的副本是 p,編譯器使 p p。如果函式體內的程式修改了 p 的內容,就導致引數p 的內容作相應...

PHP是如何管理記憶體的 這是提問帖

除錯環境 xampp 1.8.1,windows 8 x64位作業系統,記憶體8g.php在每次呼叫執行時,究竟占用了系統多少記憶體呢?許多文章僅寫到了很少,效能很高,卻沒有細緻講解,也沒有分析資料報告.今天有個需求很特殊,需要分析記憶體占用,所以寫篇文章記錄一下,掌握規律.a 1 amemory ...