linux內存管理之malloc、vmalloc、kmalloc的區別


linux內存管理之malloc、vmalloc、kmalloc的區別

 

1、kmalloc和vmalloc是分配的是內核的內存,malloc分配的是用戶的內存

2、kmalloc保證分配的內存在物理上是連續的,內存只有在要被DMA訪問的時候才需要物理上連續,malloc和vmalloc保證的是在虛擬地址空間上的連續

 

3、kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相對較大

4、vmalloc比kmalloc要慢。 盡管在某些情況下才需要物理上連續的內存塊,但是很多內核代碼都用kmalloc來獲得內存,而不是vmalloc。這主要是出於性能的考慮。vmalloc函數為了把物理內存上不連續的頁轉換為虛擬地址空間上連續的頁,必須專門建立頁表項。糟糕的是,通過vmalloc獲得的頁必須一個個地進行映射,因為它們物理上是不連續的,這就會導致比直接內存映射大得多的TLB抖動,vmalloc僅在不得已時才會用--典型的就是為了獲得大塊內存時。

malloc的實現原理

malloc函數的實質體現在,它有一個將可用的內存塊連接為一個長長的列表的所謂空閑鏈表(全局變量,一個內存塊的鏈表指針)。調用malloc函數時,它沿連接表尋找一個大到足以滿足用戶請求所需要的內存塊。然后,將該內存塊一分為二(一塊的大小與用戶請求的大小相等,另一塊的大小就是剩下的字節)。接下來,將分配給用戶的那塊內存傳給用戶,並將剩下的那塊(如果有的話)返回到連接表上。調用free函數時,它將用戶釋放的內存塊連接到空閑鏈上。到最后,空閑鏈會被切成很多的小內存片段,如果這時用戶申請一個大的內存片段,那么空閑鏈上可能沒有可以滿足用戶要求的片段了。於是,malloc函數請求延時,並開始在空閑鏈上翻箱倒櫃地檢查各內存片段,對它們進行整理,將相鄰的小空閑塊合並成較大的內存塊。  malloc()在操作系統中的實現    在 C 程序中,多次使用malloc () 和 free()。不過,您可能沒有用一些時間去思考它們在您的操作系統中是如何實現的。本節將向您展示 malloc 和 free 的一個最簡化實現的代碼,來幫助說明管理內存時都涉及到了哪些事情。   在大部分操作系統中,內存分配由以下兩個簡單的函數來處理:    void *malloc (long numbytes):該函數負責分配 numbytes 大小的內存,並返回指向第一個字節的指針。    void free(void *firstbyte):如果給定一個由先前的 malloc 返回的指針,那么該函數會將分配的空間歸還給進程的“空閑空間”。

 

malloc_init 將是初始化內存分配程序的函數。它要完成以下三件事:將分配程序標識為已經初始化,找到系統中最后一個有效內存地址,然后建立起指向我們管理的內存的指針。這三個變量都是全局變量:

如前所述,被映射的內存的邊界(最后一個有效地址)常被稱為系統中斷點或者當前中斷點。在很多 UNIX? 系統中,為了指出當前系統中斷點,必須使用sbrk(0) 函數。 sbrk 根據參數中給出的字節數移動當前系統中斷點,然后返回新的系統中斷點。使用參數 0 只是返回當前中斷點。這里是我們的 malloc 初始化代碼,它將找到當前中斷點並初始化我們的變量

 

現在,為了完全地管理內存,我們需要能夠追蹤要分配和回收哪些內存。在對內存塊進行了 free 調用之后,我們需要做的是諸如將它們標記為未被使用的等事情, 並且, 在調用 malloc 時, 我們要能夠定位未被使用的內存塊。 因此, malloc返回的每塊內存的起始處首先要有這個結構:

現在, 您可能會認為當程序調用 malloc 時這會引發問題 —— 它們如何知道這個結構?答案是它們不必知道;在返回指針之前,我們會將其移動到這個結構之后, 把它隱藏起來。 這使得返回的指針指向沒有用於任何其他用途的內存。 那樣,從調用程序的角度來看,它們所得到的全部是空閑的、開放的內存。然后,當通過 free() 將該指針傳遞回來時,我們只需要倒退幾個內存字節就可以再次找到這個結構。在討論分配內存之前,我們將先討論釋放,因為它更簡單。為了釋放內存,我們必須要做的惟一一件事情就是,獲得我們給出的指針,回退 sizeof(structmem_control_block) 個字節,並將其標記為可用的。這里是對應的代碼:

如您所見,在這個分配程序中,內存的釋放使用了一個非常簡單的機制,在固定時間內完成內存釋放。分配內存稍微困難一些。我們主要使用連接的指針遍歷內存來尋找開放的內存塊。這里是代碼:

這就是我們的內存管理器。現在,我們只需要構建它,並在程序中使用它即可.多次調用 malloc()后空閑內存被切成很多的小內存片段,這就使得用戶在申請內存使用時,由於找不到足夠大的內存空間,malloc()需要進行內存整理,使得函數的性能越來越低。聰明的程序員通過總是分配大小為 2 的冪的內存塊,而最大限度地降低潛在的 malloc 性能喪失。也就是說,所分配的內存塊大小為4 字節、8 字節、16 字節、18446744073709551616 字節,等等。這樣做最大限度地減少了進入空閑鏈的怪異片段(各種尺寸的小片段都有)的數量。盡管看起來這好像浪費了空間,但也容易看出浪費的空間永遠不會超過 50%。

 


免責聲明!

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



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