① linux用戶進程是如何釋放內存的
從圖中我們可以看出,進程的堆,並不是直接建立在Linux的內核的內存分配策略上的,而是建立在glibc的堆管理策略上的(也就是glibc的動態內存分配策略上),堆的管理是由glibc進行的。所以我們調用free對mal
Linux進程使用內存的基本流程:
從圖中我們可以看出,進程的堆,並不是直接建立在Linux的內核的內存分配策略上的,而是建立在glibc的堆管理策略上的(也就是glibc的動態內存分配策略上),堆的管理是由glibc進行的。所以我們調用free對malloc得到的內存進行釋放的時候,並不是直接釋放給操作系統,而是還給了glibc的堆管理實體,而glibc會在把實際的物理內存歸還給系統的策略上做一些優化,以便優化用戶任務的動態內存分配過程。
它會從堆的最大線性地址開始,從後向前計算用戶任務當前有多少空閑的堆內存(直到碰到使用中的堆內存地址為止),比如在該圖中:
它會認為有2048k的可釋放內存,只有在該值大於某個特定的threshhold時(2.3.6上為64k),它才會把這些內存歸還給系統。而在中間的未使用內存是不會歸還給系統的,所以系統也不可能再利用這塊物理內存頁(我們假設系統沒有swap區和swap文件),也就是說系統的內存會為此減少,除非在它之前的堆內存都用free進行釋放以後,glibc的堆管理器才有可能(只是有可能)把該段內存歸還給系統。
② Linux用戶空間內存是怎麼動態申請
用戶空間中動態申請內存的函數為malloc (),這個函數在各種操作系統上的使用都是一致的,malloc ()申請的內存的釋放函數為free()。對於Linux而言,C庫的malloc ()函數一般通過brk ()和mmap ()兩個系統調用從內核申請內存。由於用戶空間C庫的malloc演算法實際上具備一個二次管理能力,所以並不是每次申請和釋放內存都一定伴隨著對內核的系統調用。比如,代碼清單11.2的應用程序可以從內核拿到內存後,立即調用free(),由於free()之前調用了mallopt(M_TRIM_THRESHOLD,一1)和mallopt (M_MMAP_MAX,0),這個free ()並不會把內存還給內核,而只是還給了C庫的分配演算法(內存仍然屬於這個進程),因此之後所有的動態內存申請和釋放都在用戶態下進行。另外,Linux內核總是採用按需調頁(Demand Paging),因此當malloc ()返回的時候,雖然是成功返回,但是內核並沒有真正給這個進程內存,這個時候如果去讀申請的內存,內容全部是0,這個頁面的映射是只讀的。只有當寫到某個頁面的時候,內核才在頁錯誤後,真正把這個頁面給這個進程。
在Linux內核空間中申請內存涉及的函數主要包括kmalloc( ) 、get free pages ( )和vmalloc ()
等。kmalloc ()和_get_free pages ()(及其類似函數)申請的內存位於DMA和常規區域的映射區,而且在物理上也是連續的,它們與真實的物理地址只有一個固定的偏移,因此存在較簡單的轉換關系。而vmalloc()在虛擬內存空間給出一塊連續的內存區,實質上,這片連續的虛擬內存在物理內存中並不一定連續,而vmalloc ()申請的虛擬內存和物理內存之間也沒有簡單的換算關系。
③ malloc怎麼使用,請舉例說明,謝謝!
malloc使用須要包括頭文件:
#include 'stdlib.h'
例如:
int *p;
p = new int; /返回類型為int* 類型(整數型指針)。分配大小為 sizeof(int);
或:
int* parr;
parr = new int [100]; //返回類型為 int* 類型(整數型指針)。分配大小為 sizeof(int) * 100;
而 malloc 則必須由我們計算要位元組數,而且在返回後強行轉換為實際類型的指針。
int* p;
p = (int *) malloc (sizeof(int));
malloc 函數返回的是 void * 類型。
對於C++,如果你寫成:p = malloc (sizeof(int)); 則程序無法通過編譯,報錯:「不能將 void* 賦值給 int * 類型變數」。
所以必須通過 (int *) 來將強制轉換。而對於C,沒有這個要求,但為了使C程序更方便的移植到C++中來,養成強制轉換的習慣。
在Linux中可以有這樣:malloc(0),這是因為Linux中malloc有一個下限值16Bytes,注意malloc(-1)是禁止的;但是在某些系統中是不允許malloc(0)的。
在規范的程序中我們有必要按照這樣的格式去使用malloc及free:
type*p;
if(NULL==(p=(type*)malloc(sizeof(type))))
/*請使用if來判斷,這是有必要的*/
{
perror("error...");
exit(1);
}
.../*其它代碼*/
free(p);
p=NULL;/*請加上這句*/