brk和sbrk工作原理


 sbrk/brk: brk和sbrk主要的工作是實現虛擬內存到內存的映射.在GNUC中,內存分配是這樣的:
      每個進程可訪問的虛擬內存空間爲3G,但在程序編譯時,不可能也沒必要爲程序分配這麼大的空間,只分配並不大的數據段空間,程序中動態分配的空間就是從這一塊分配的。如果這塊空間不夠,malloc函數族(realloc,calloc等)就調用sbrk函數將數據段的下界移動,sbrk函數在內核的管理下將虛擬地址空間映射到內存,供malloc函數使用。(參見linux內核情景分析)

      sbrk不是系統調用,是C庫函數。系統調用通常提供一種最小功能,而庫函數通常提供比較複雜的功能。sbrk/brk是從堆中分配空間,本質是移動一個位置,向後移就是分配空間,向前移就是釋放空間,sbrk用相對的整數值確定位置,如果這個整數是正數,會從當前位置向後移若干字節,如果爲負數就向前若干字節。在任何情況下,返回值永遠是移動之前的位置

      在LINUX中sbrk(0)能返回比較精確的虛擬內存使用情況,比如squid用它來計算內存的使用!在SOLARIS/HP中sbrk(0)返回以頁爲單位的虛擬內存使用情況。使用sbrk(0)來返回程式當前使用了多少內存。

  1. main(){  
  2. int start,end;  
  3. start = sbrk(0);  
  4. ....  
  5. malloc(***);  
  6. ....  
  7. end = sbrk(0);  
  8. printf("hello I used %d vmemory",end - start);  
  9. }  

 brk用絕對的地址指定移到哪個位置。

  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. int main()  
  4. {  
  5.  void* p = sbrk(0);  
  6.  int* p1 = p;  
  7.  brk(p1+4);//分配了16個字節的空間  
  8.  p1[0] = 10;  
  9.  p1[1] = 20;  
  10.  p1[2] = 30;  
  11.  p1[3] = 40;  
  12.  p1[4] = 50;  
  13.  int* p2 = sbrk(4);  
  14.  printf("*p2=%d\n", *p2);  
  15.  brk(p1+1024);//分配整個頁面的空間  
  16.  brk(p1+512);//釋放一半空間  
  17.  brk(p1);//釋放所有空間  
  18. }  

sbrk:

 參數>0 向後移動當前位置,相當分配內存空間

 參數<0 向前移動當前位置,相當釋放內存空間

 參數==0 當前位置不動

 >0 <0 ==0  返回總是移動前的位置

 brk(void* ptr);

 將當前位置移動到ptr的位置

 ptr的位置一般通過sbrk(0)獲取首地址,然後再計算得出、


一些sbrk實例:

  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. int main()  
  4. {  
  5.  /*分配10個字節的空間,返回該空間的首地址*/  
  6.  void* p = sbrk(12);  
  7.  void* p2 = sbrk(4);  
  8.  void* p3 = sbrk(4);  
  9.  void* p4 = sbrk(4);  
  10.  printf("p=%p\n", p);  
  11.  printf("p2=%p\n", p2);  
  12.  printf("p3=%p\n", p3);  
  13.  printf("p4=%p\n", p4);  
  14.  /*用參數爲0來獲取未分配空間的開始位置*/  
  15.  void* p0 = sbrk(0);  
  16.  printf("p0=%p\n", p0);  
  17.  void* p5 = sbrk(-4);  
  18.  printf("p5=%p\n", p5);  
  19.  printf("pid=%d\n", getpid());  
  20.  sleep(10);  
  21.  /*當釋放到一個頁面的開始位置時,整個頁面會被操作系統回收*/  
  22.  sbrk(-20);  
  23.    
  24.  /* 
  25.  int* pi = p; 
  26.  *pi = 10; 
  27.  *(pi+1) = 20; 
  28.  *(pi+2) = 30; 
  29.  *(pi+1023) = 1023; 
  30.   *(pi+1024) = 1024; 
  31.  */  
  32.   
  33.  while(1);  
  34. }  
  35.    
  36. #include <stdio.h>  
  37. #include <unistd.h>  
  38. int main()  
  39. {  
  40.  printf("pid=%d\n", getpid());  
  41.  void* p = sbrk(0);  
  42.  int* p1 = sbrk(4);  
  43.  sleep(10);  
  44.  int* p2 = sbrk(1023*4+1);  
  45.  sleep(10);  
  46.  sbrk(-1);  
  47.  while(1);  
  48. }  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章