Linux記憶體管理概括

2021-06-22 08:31:52 字數 3697 閱讀 1099

(1)頁框:物理記憶體的描述,必須牢牢記住,頁框就是物理記憶體

(2)頁描述符:描述每乙個頁框的狀態資訊,所有的也描述符都儲存在mem_map[ ]陣列中,每個描述符32個位元組

(3)節點:系統物理記憶體被劃分為多個節點,每個節點內cpu訪問頁面的時間是相同的,對應的資料結構:節點描述符

(4)管理區:每個節點又分為多個管理區,對應的資料結構: 管理區描述符

重點介紹核心頁表的管理,主要分為兩個階段:啟動階段對映8m的頁表和剩餘頁表的對映階段

(1)啟動階段8m頁表的對映過程

(2)剩餘頁表的對映過程

幾個比較重要的位址轉換:

從核心看來,整個4g的位址空間是這樣的。

程序可用的位址空間是被乙個叫mm_struct(程序位址空間描述符)結構體來管理的,同乙個程序內的多個執行緒是共享這個資料結構的。

同時,對於使用者程序來說,每乙個程序有乙個獨一無二的mm_struct,但是核心執行緒確不是必須的。下面是操作mm_struct的一些函式。

當然如果在程序建立的時候指定子程序共享父程序的虛擬位址空間的話,比如:

if ( clone_flags & clone_vm )

還有一點許喲阿注意的就是系統中的第乙個mm_struct是需要靜態初始化的,以後的所有的mm_strcut都是通過拷貝生成的。

mmap函式,記憶體對映函式

該函式的主要功能是在程序位址空間中建立乙個線性區。有兩種型別的記憶體對映:共享型和私有型。二者的主要區別可以理解成是否對其他程序可見。共享型每次對線性區的讀寫都會修改

磁碟檔案,乙個程序修改共享型的線性區,其他對映這一線性區的所有程序都是可見的。與記憶體對映相關的資料結構:

(1)與所對映的檔案相關的索引節點物件

(2)所對映檔案的address_space物件

(3)不同程序對同一檔案進行不同對映所使用的檔案物件

(4)對檔案進行每一不同對映所使用的vm_area_struct

(5)對檔案進行對映的線性區所分配的每個頁框對應的描述符

從圖上能看出乙個檔案對應乙個inode,對應乙個address_space,對應多個struct file, 對應多個vm_area_file ,對應多個page(頁框),當然也對應多個page(頁描述符)、

mm_struct 記憶體描述符中的兩棵樹: 當前程序內所有線性區的乙個鍊錶和所有線性區的紅黑樹

mmap和mm_rb都可以訪問線性區。事實上,它們都指向了同乙個vm_area_struct結構,只是鏈結的方式不同

mmap指向的線性區鍊錶用來遍歷整個程序的位址空間

紅黑樹mm_rb用來定位乙個給定的線性位址落在程序位址空間中的哪乙個線性區中

另外,mmap_cache用來快取最近用過的線性區

address_space中的兩棵樹:基數和優先順序搜尋數。

address_space的page_tree指向了組織構成這個檔案的所有的頁描述符的基樹

address_space的i_mmap指向了組織構成這個檔案的所有的線性區描述符的基樹

要注意乙個問題:

(1)共享記憶體對映的頁通常儲存在也快取記憶體中,私有記憶體對映的頁只要還沒有修改,也儲存在頁快取記憶體中。當程序試圖修改乙個私有對映的頁時,核心

就把該頁框進行複製,並在程序頁表中用複製的頁替換原來的頁,這就是寫時複製的基礎。複製後的頁框就不會放在頁告訴快取中了,原因是它不再是表示磁碟上那

個檔案的有效資料。

(2)線性區的開始和結束位址都是4k對齊的

程序獲得新線性區的一些典型情況

:剛剛建立的新程序

使用exec系統呼叫裝載乙個新的程式執行

將乙個檔案(或部分)對映到程序位址空間中

當使用者堆疊不夠用的時候,擴充套件堆疊對應的線性區

建立記憶體對映:

要想建立乙個對映,就要呼叫mmap, mmap()最終會呼叫do_mmap()

static inline unsigned long do_mmap(struct file *file, unsigned long

addr, unsigned long len, unsigned long prot,  unsigned long

flag,unsigned long offset)                    

file:要對映的檔案描述符,知道對映哪個檔案才行

offset:檔案內的偏移量,指定要對映檔案的一部分,當然也可以是全部

len: 要對映檔案的那一部分的長度

flag:一組標誌,顯示的指定對映的那部分是map_shared或map_private

prot: 一組許可權,指定對線性區訪問的一種或多種訪問許可權

addr: 乙個可選的線性位址,表示從這個位址之後的某個位置建立線性區

基本的過程是:

(2)做一些許可權和標誌位檢查

(3)將檔案物件的位址struct file位址賦值給線性區描述符vm_area_struct.vm_file

(4)呼叫mmap方法,這個方法最後呼叫generic_file_mmap()

其他線性區處理函式

(1)find_vma() : 查詢乙個線性位址所屬的線性區或後繼線性區

(2)find_vmm_interrection(): 查詢乙個與給定區間重疊的線性區

(4)insert_vm_struct () : 向程序的記憶體描述符中插入乙個線性區

缺頁異常處理程式

(1)背景知識

核心中的函式以直接了當的方式獲得動態記憶體,核心是作業系統中優先順序最高的成分,核心信任自己,採用面級記憶體分配和小記憶體分配以及非連續線性區得到記憶體

使用者態程序分配記憶體時,請求被認為是不緊迫的,使用者程序不可信任,因此,當使用者態程序請求動態記憶體時,並沒有立即獲得實際的物理頁框,而僅僅獲得對乙個

新的線性位址區間的使用權這個線性位址區間會成為程序位址空間的一部分,稱作線性區(memory areas)。 這樣,當使用者進**正向這些線性區寫的時候,就會

產生缺頁異常,在缺頁異常處理程式中獲得真正的物理記憶體。

(2)缺頁異常處理程式需要區分引起缺頁的兩種情況:程式設計錯引起的缺頁和屬於程序的位址空間尚未分配到物理頁框

簡單流程圖:

詳細流程圖:

linux為什麼要分為三個區:zone_dma  zone_normal zone_highmem?

(1)isa匯流排的歷史遺留問題,只能訪問記憶體的前16m的空間

(2)大容量的ram使得線性位址空間太小,並不是所有的物理空間都能對映到唯一的線性位址空間

如何確定某個頁框屬於哪個節點或管理區?

是由每個頁框描述符中的flag的高位索引的,比如page_zone()函式就是接收頁描述符的位址作為引數,返回頁描述符中flag的高位,並到zone_table[ ]陣列中確定相應的管理區描述符的位址

slab演算法是用來滿足對以頁框為單位的請求而設定的,簡單介紹以下slab演算法的原理

對於以頁為單位的請求傳送到管理區分配器,然後管理區分配器搜尋它所管轄的管理區,找乙個滿足請求的分配區,然後再由這個管理區中的夥伴系統去處理,為了加快這個

過程,每個分割槽中還提供了乙個每cpu頁框快取記憶體,來處理單個頁框的請求。

這個過程中有四個請求頁框的函式和巨集:

(1)alloc_pages, alloc_page返回分配的第乙個頁框的頁描述符的位址

(2)__get_free_pages , __get_free_page 返回分配的第乙個頁框的線性位址

其實二者是相同,因為有專門用來處理線性位址到頁描述符位址轉換的函式   virt_to_page()  實現從線性位址到頁描述符位址的轉換

Linux記憶體管理

本文首先介紹一下linux記憶體管理方式,著重說明一下使用者空間的記憶體管理,包括linux虛擬對映以及glibc中malloc的實現 然後簡要介紹單程序多執行緒的記憶體管理方式,主要涉及各執行緒堆疊空間的分配 linux 採用兩級保護機制,隔離核心空間和使用者程式空間,使使用者程式無法直接訪問核心...

Linux記憶體管理

本文首先介紹一下linux記憶體管理方式,著重說明一下使用者空間的記憶體管理,包括linux虛擬對映以及glibc中malloc的實現 然後簡要介紹單程序多執行緒的記憶體管理方式,主要涉及各執行緒堆疊空間的分配 linux採用兩級保護機制,隔離核心空間和使用者程式空間,使使用者程式無法直接訪問核心,...

Linux記憶體管理

首先我要說,我這是轉貼,轉的cu論壇上 nonameboy 的帖子,你可以連線過去看看。今天因為要解釋系統中可用記憶體的大小,用google看了半天,還有在cu上找了關天,竞然沒有發現有比較好的章,估計很多人都沒有注意到,懂了以後又沒有整理出來。在cu上看了很多文章說什麼memory leak和li...