關於linux記憶體的管理

2021-06-22 11:19:43 字數 2230 閱讀 4003

(1)  最近又稍微看了linux記憶體的管理,又稍微有一點收穫,來這裡記錄一下,以防以後又忘記了。(都是針對32位的線性位址)

首先是linux核心中從邏輯位址到實體地址的轉化。由於x86要支援段式對映,l段式對映是將段描述符中的基位址加上偏移量的定址方式。ldtr或者gdtr暫存器指向段描述符表的首位址,16位段選擇暫存器中的前13位用於選擇是段描述符表中的對應項(也就是段描述符),後三位包括許可權檢查、選擇ldtr或者gdtr暫存器等。段描述中需要關注的是base欄位,是段對映中的基位址。linux中為了相容雖然也用了段對映,但是base都是0x0000000,所以在linux中邏輯位址等於線性位址。段對映就講這麼多了,不是重點,頁對映才是重點。

上面講到由邏輯位址轉化為了線性位址(linux其實是相等的)。線性位址通過頁對映轉換為實體地址。頁對映把32位的線性位址劃分為3段,前10位頁目錄項,中間10位頁面項,後12位是頁內偏移。暫存器cr3中存放當前使用的頁表項基位址,指向程序的頁表項。每個程序都有乙個頁表項,當發生程序切換的時候要更改cr3中的值以使用自己的程序空間。定址過程是:

1.通過cr3找到頁目錄表的基位址,然後通過線性位址的前10位找到相應偏移的頁目錄項,該目錄項中存放相應頁表的基位址。

2.找到頁表基位址後,通過中間10位找到相應偏移的頁表項。

3.通過偏移量找到相應偏移的位元組。

(2)linux中4g的線性位址空間,核心佔1g(0xc0000000以上),使用者空間站低3g。值得一提的是在1g的核心空間中分為3個區:dma,normal,highmemory三個區。dma一般低16m,normal(16~896m),高128m是highmemory。其中dma區和normal區在linux啟動完成後一般是固定映**物理記憶體的低896m頁框,這也就是為什麼在核心中有實體地址和線性位址間的轉換只要加上或者減去0xc0000000。這裡的記憶體可以通過kmalloc或者 get_free_pages獲取,這兩個函式獲取的是直接是線性位址。alloc_pages獲取的是頁框位址,要獲得線性位址還要進行相應的轉化。page_address可以進行轉化,page_address先判斷是否是高階記憶體,如果不是直接加上0xc0000000就是線性位址。如果是則比較複雜,先檢查是否已經映**相應的線性位址有就直接返回位址,沒有就要分配頁目錄和頁面進行對映,然後返回線性位址。

高階記憶體是沒有對映的,使用的時候要臨時進行對映到線性位址。

1、永久核心對映:直到取消對映才不能用了。kmap進行永久對映,這種對映可能會睡眠。

2、臨時核心對映:kmap_atomic進行臨時對映,程序不會睡眠;

永久核心對映和臨時核心對映,都由核心指定了需要進行對映的頁面,也就是說指定了頁描述符(頁描述符和物理頁框之間的關係是固定不可變的),在永久核心對映中,核心只需要在永久核心對映區找到空閒的,也就是未被對映的線性位址對應的頁表項,然後將其分配給page即可,若找不到則將阻塞申請建立對映的程序;而臨時核心對映更直接,連進行對映的線性位址視窗都是固定的,若是其已經分配給了某個頁框,則直接搶過來用,因此之前的對映就被覆蓋了(那麼怎麼保證資料安全呢?看到大概有兩種保證:1.這個區域是percpu的,也就是每個cpu都有乙個。2.在進行臨時對映的時候要禁止中斷,防止搶占。),體現出了臨時性。非連續記憶體分配,核心不用指定具體的page,只需指定要申請的記憶體大小,核心將在非連續記憶體分配區找到一塊相應大小虛擬位址空間,然後再由夥伴系統分配頁框,還要通過slab分配器為一些資料結構分配記憶體,最後再用同樣的方式(設定pte表項)來建立對映。

詳細解釋見:

(3)程序位址空間

程序的位址空間在建立程序時分配,開始分配的時候是沒有對映到實體地址的。只有在使用的時候發現對應線性位址的頁表不存在則產生乙個缺頁異常,核心捕獲到這個異常後開始對映,分配頁目錄和頁面項,分配物理頁框。程式設計引發的記憶體錯誤不一樣,記憶體錯誤可能是由於不再程序位址空間,或者許可權不夠的時候產生,核心傳送sigsegv訊號,產生段錯誤。

linux程序位址空間由程序描述符中的struct  mm_struct指向。mm中包括各種線性區的位址和長度。每個程序空間可能包含很多個不連續線性區,mm中分別用鍊錶和紅黑樹組織線性區,一般遍

歷時用鍊錶,查詢時用紅黑樹。每個程序空間最多可以有65536個線性區,在/proc/中可以更改這個數字。每個線性區由struct  vm_area_struct表示,包括線性區的起始位址。

下面是一張線性位址空間組織圖。

關於記憶體管理

簡單的理解,可以將記憶體分為三個部分 靜態區,棧和堆,三個部分都有自己的許可權,不可以隨便讀寫。靜態區 儲存自動全域性變數和static變數,靜態區的內容在總的程式的生命週期都存在,由編譯器在編譯的時候分配。棧 儲存區域性變數。棧上的內容只在函式的範圍內存在,當函式結束,這些內容也會被自動銷毀,效率...

關於記憶體管理

什麼是記憶體管理?是指軟體執行時對計算機記憶體資源的分配和使用技術。其最主要的目的就是如何高效 快速的分配,並且在適當的時候釋放和 記憶體資源。在 ios 中資料是存在堆和棧中的,然而我們的記憶體管理管理的是堆上的記憶體,棧上的記憶體並不需要我們管理。引用計數是計算機程式語言中的一種記憶體管理技術,...

關於記憶體管理

記憶體管理涉及根據資料庫更改的需求為oracle database例項記憶體結構維護最佳大小。必須管理的記憶體結構是系統全域性區域 sga 和例項程式全域性區域 例項pga oracle資料庫支援各種由初始化引數設定選擇的記憶體管理方法。oracle建議您啟用稱為自動記憶體管理的方法。自動記憶體管理...