malloc原理和記憶體碎片

2022-07-10 05:06:11 字數 2706 閱讀 7409

當乙個程序發生缺頁中斷的時候,程序會陷入核心態,執行以下操作: 

1、檢查要訪問的虛擬位址是否合法

2、查詢/分配乙個物理頁 

3、填充物理頁內容(讀取磁碟,或者直接置0,或者啥也不幹) 

4、建立對映關係(虛擬位址到實體地址)

重新執行發生缺頁中斷的那條指令 

如果第3步,需要讀取磁碟,那麼這次缺頁中斷就是majflt,否則就是minflt。

記憶體分配的原理

從作業系統角度來看,程序分配記憶體有兩種方式,分別由兩個系統呼叫完成:brk和mmap(不考慮共享記憶體)。

1、brk是將資料段(.data)的最高位址指標_edata往高位址推;

2、mmap是在程序的虛擬位址空間中(堆和棧中間,稱為檔案對映區域的地方)找一塊空閒的虛擬記憶體

這兩種方式分配的都是虛擬記憶體,沒有分配物理記憶體在第一次訪問已分配的虛擬位址空間的時候,發生缺頁中斷,作業系統負責分配物理記憶體,然後建立虛擬記憶體和物理記憶體之間的對映關係。

在標準c庫中,提供了malloc/free函式分配釋放記憶體,這兩個函式底層是由brk,mmap,munmap這些系統呼叫實現的。

下面以乙個例子來說明記憶體分配的原理:

情況一、malloc小於128k的記憶體,使用brk分配記憶體,將_edata往高位址推(只分配虛擬空間,不對應物理記憶體(因此沒有初始化),第一次讀/寫資料時,引起核心缺頁中斷,核心才分配對應的物理記憶體,然後虛擬位址空間建立對映關係),如下圖:

1、程序啟動的時候,其(虛擬)記憶體空間的初始布局如圖1所示。

其中,mmap記憶體對映檔案是在堆和棧的中間(例如libc-2.2.93.so,其它資料檔案等),為了簡單起見,省略了記憶體對映檔案。

malloc函式會呼叫brk系統呼叫,將_edata指標往高位址推30k,就完成虛擬記憶體分配。

你可能會問:只要把_edata+30k就完成記憶體分配了?

事實是這樣的,_edata+30k只是完成虛擬位址的分配,a這塊記憶體現在還是沒有物理頁與之對應的,等到程序第一次讀寫a這塊記憶體的時候,發生缺頁中斷,這個時候,核心才分配a這塊記憶體對應的物理頁。也就是說,如果用malloc分配了a這塊內容,然後從來不訪問它,那麼,a對應的物理頁是不會被分配的。

3、程序呼叫b=malloc(40k)以後,記憶體空間如圖3。

情況二、malloc大於128k的記憶體,使用mmap分配記憶體,在堆和棧之間找一塊空閒記憶體分配(對應獨立記憶體,而且初始化為0),如下圖:

4、程序呼叫c=malloc(200k)以後,記憶體空間如圖4:

預設情況下,malloc函式分配記憶體,如果請求記憶體大於128k(可由m_mmap_threshold選項調節),那就不是去推_edata指標了,而是利用mmap系統呼叫,從堆和棧的中間分配一塊虛擬記憶體。

這樣子做主要是因為::

brk分配的記憶體需要等到高位址記憶體釋放以後才能釋放(例如,在b釋放之前,a是不可能釋放的,這就是記憶體碎片產生的原因,什麼時候緊縮看下面),而mmap分配的記憶體可以單獨釋放。

當然,還有其它的好處,也有壞處,再具體下去,有興趣的同學可以去看glibc裡面malloc的**了。 

5、程序呼叫d=malloc(100k)以後,記憶體空間如圖5;

6、程序呼叫free(c)以後,c對應的虛擬記憶體和物理記憶體一起釋放。

7、程序呼叫free(b)以後,如圖7所示:

b對應的虛擬記憶體和物理記憶體都沒有釋放,因為只有乙個_edata指標,如果往回推,那麼d這塊記憶體怎麼辦呢

當然,b這塊記憶體,是可以重用的,如果這個時候再來乙個40k的請求,那麼malloc很可能就把b這塊記憶體返回回去了。 

8、程序呼叫free(d)以後,如圖8所示:

b和d連線起來,變成一塊140k的空閒記憶體。

9、預設情況下:

當最高位址空間的空閒記憶體超過128k(可由m_trim_threshold選項調節)時,執行記憶體緊縮操作(trim)。在上乙個步驟free的時候,發現最高位址空閒記憶體超過128k,於是記憶體緊縮,變成圖9所示。

malloc記憶體分配原理

一 malloc的工作機制 它有乙個將可用的記憶體塊連線為乙個長長的列表的所謂空閒鍊錶。呼叫malloc函式時,它沿連線表尋找乙個大到足以滿足使用者請求所需要的記憶體塊。然後,將該記憶體塊一分為二 一塊的大小與使用者請求的大小相等,另一塊的大小就是剩下的位元組 接下來,將分配給使用者的那塊記憶體傳給...

malloc記憶體分配原理

一 malloc的工作機制 它有乙個將可用的記憶體塊連線為乙個長長的列表的所謂空閒鍊錶。呼叫malloc函式時,它沿連線表尋找乙個大到足以滿足使用者請求所需要的記憶體塊。然後,將該記憶體塊一分為二 一塊的大小與使用者請求的大小相等,另一塊的大小就是剩下的位元組 接下來,將分配給使用者的那塊記憶體傳給...

記憶體管理 內部碎片和外部碎片

概念 乙個分割槽內部出現的碎片 即被浪費的空間 不能被利用。能明確指出屬於哪個程序 例子 固定分割槽法中,當6kb的程序被分配了10kb的記憶體空間,就有4kb的內部碎片 乙個程序申請43kb的記憶體空間,某些處理器因為限制 比如其體系結構規定只能整除4 8 16 該程序被分配了44kb,就有1kb...