武漢電腦培訓資訊:【武漢華嵌】內(nèi)存分配函數(shù)用法小結

武漢
當前位置:求學問校網(wǎng)首頁>武漢資訊>武漢電腦培訓資訊

【武漢華嵌】內(nèi)存分配函數(shù)用法小結

來源:求學問校網(wǎng)     發(fā)表時間:2011-10-26     瀏覽 50

作者:武漢華嵌技術部

 

一、用戶空間內(nèi)存分配:malloc、calloc、realloc

1、malloc原型如下:

extern void *malloc(unsigned int num_bytes);

功能:

分配長度為num_bytes字節(jié)塊。

工作機制:

malloc函數(shù)的實質(zhì)體現(xiàn)在,它有一個將可用的內(nèi)存塊連接為一個長長的列表的所謂空閑鏈表。調(diào)用malloc函數(shù)時,它沿連接表尋找一個大到足以滿足用戶請求所需要的內(nèi)存塊。然后,將該內(nèi)存塊一分為二(一塊的大小與用戶請求的大小相等,另一塊的大小就是剩下的字節(jié))。接下來,將分配給用戶的那塊內(nèi)存?zhèn)鹘o用戶,并將剩下的那塊(如果有的話)返回到連接表上。

 

2、calloc原型如下:

void *calloc(unsigned n,unsigned size);

功能:

在內(nèi)存的動態(tài)存儲區(qū)中分配n個長度為size的連續(xù)空間。

 

3、realloc原型如下:

extern void *realloc(void *mem_address, unsigned int newsize);

功能:

先按照newsize指定的大小分配空間,將原有數(shù)據(jù)從頭到尾拷貝到新分配的內(nèi)存區(qū)域,而后釋放原來mem_address所指內(nèi)存區(qū)域,同時返回新分配的內(nèi)存區(qū)域的首地址。即重新分配存儲器塊的地址。

 

注意:malloc和calloc的區(qū)別:

calloc在動態(tài)分配完內(nèi)存后,自動初始化該內(nèi)存空間為零,而malloc不初始化,里邊數(shù)據(jù)是隨機的垃圾數(shù)據(jù)。

 

realloc注意事項:

  a、realloc失敗的時候,返回NULL。

  b、realloc失敗的時候,原來的內(nèi)存不改變,不會釋放也不會移動。

  c、假如原來的內(nèi)存后面還有足夠多剩余內(nèi)存的話,realloc的內(nèi)存等于原來的內(nèi)存加上剩余內(nèi)存,realloc還是返回原來內(nèi)存的地址; 假如原來的內(nèi)存后面沒有足夠多剩余內(nèi)存的話,realloc將申請新的內(nèi)存,然后把原來的內(nèi)存數(shù)據(jù)拷貝到新內(nèi)存里,原來的內(nèi)存將被free掉,realloc返回新內(nèi)存的地址。

  d、如果size為0,效果等同于free()。

  e、傳遞給realloc的指針必須是先前通過malloc(), calloc(), 或realloc()分配的。

f、傳遞給realloc的指針可以為空,等同于malloc。

 

以上三者的事例代碼如下:

#include <stdio.h>

#include <malloc.h>

#include <string.h>

 

int main()

{

  //最好每次內(nèi)存申請都檢查申請是否成功

  //下面這段僅僅作為演示的代碼沒有檢查

      char *pt1;

      char *pt2;

      char *pt3;

     

      pt1 = (char *)malloc(sizeof(char)ၲ);

      printf("pt1 = %p\n", pt1);

      //以下可能會輸出亂碼,說明malloc分配的空間沒有被初始化為0

      printf("%s\n", pt1);

      scanf("%s", pt1);

     

      pt2 = (char *)calloc(10,sizeof(char));

      printf("pt2 = %p\n", pt2);

      //以下輸出為空,說明calloc分配的空間被初始化為0

      printf("%s\n", pt2);    

 

      pt3 = (char *)realloc(pt1, sizeof(char)ၼ);

      printf("pt3 = %p\n", pt3);

      //以下輸出pt1中原先的內(nèi)容。

      printf("%s\n", pt3);

 

      //以下是釋放申請的內(nèi)存空間

      free(pt2);

      free(pt3);

      return 0;

}

 

二、內(nèi)核空間內(nèi)存分配:kmalloc、vmalloc

       對于提供了MMU(存儲管理器,輔助操作系統(tǒng)進行內(nèi)存管理,提供虛實地址轉(zhuǎn)換等硬件支持)的處理器而言,Linux提供了復雜的存儲管理系統(tǒng),使得進程所能訪問的內(nèi)存達到4GB。

進程的4GB內(nèi)存空間被人為的分為兩個部分--用戶空間與內(nèi)核空間。用戶空間地址分布從0到3GB(PAGE_OFFSET,在0x86中它等于0xC0000000),3GB到4GB為內(nèi)核空間。

從前面的介紹已經(jīng)看出,這兩個函數(shù)所分配的內(nèi)存都處于內(nèi)核空間,即從3GB~4GB;但位置不同,kmalloc()分配的內(nèi)存處于3GB~high_memory之間,這一段內(nèi)核空間與物理內(nèi)存的映射一一對應,而vmalloc()分配的內(nèi)存在vmalloc_start~4GB之間,這一段連續(xù)內(nèi)存區(qū)映射到物理內(nèi)存也可能是非連續(xù)的。

   vmalloc()工作方式與kmalloc()類似,其主要差別在于前者分配的物理地址無需連續(xù),而后者確保頁在物理上是連續(xù)的(虛地址自然也是連續(xù)的)。

盡管僅僅在某些情況下才需要物理上連續(xù)的內(nèi)存塊,但是,很多內(nèi)核代碼都調(diào)用kmalloc(),而不是用vmalloc()獲得內(nèi)存。這主要是出于性能的考慮。vmalloc()函數(shù)為了把物理上不連續(xù)的頁面轉(zhuǎn)換為虛擬地址空間上連續(xù)的頁,必須專門建立頁表項。還有,通過vmalloc()獲得的頁必須一個一個的進行映射(因為它們物理上不是連續(xù)的),這就會導致比直接內(nèi)存映射大得多的緩沖區(qū)刷新。因為這些原因,vmalloc()僅在絕對必要時才會使用——典型的就是為了獲得大塊內(nèi)存時,例如,當模塊被動態(tài)插入到內(nèi)核中時,就把模塊裝載到由vmalloc()分配的內(nèi)存上。

kamlloc函數(shù)原型:

#include<linux/slab.h>

void *kmalloc(size_t size, int flags);

(1)第一個參數(shù)是要分配的塊的大小

(2)第二個參數(shù)是分配標志(flags),他提供了多種kmalloc的行為。

 

vamlloc函數(shù)原型:

#include <linux/vmalloc.h>
void *vmalloc(unsigned long size);

(1)第一個參數(shù)是要分配的塊的大小

 

我們用下面的程序來演示kmalloc和vmalloc的區(qū)別:

#include <linux/module.h>

#include <linux/slab.h>

#include <linux/vmalloc.h>

MODULE_LICENSE("GPL");

unsigned char *kmallocmem;

unsigned char *vmallocmem;

int __init mem_module_init(void)

{

  //最好每次內(nèi)存申請都檢查申請是否成功

  //下面這段僅僅作為演示的代碼沒有檢查

  kmallocmem = (unsigned char*)kmalloc(100, 0);

  printk("<1>kmallocmem addr=%x", kmallocmem);

  vmallocmem = (unsigned char*)vmalloc(1000000);

  printk("<1>vmallocmem addr=%x", vmallocmem);

  return 0;

}

void __exit mem_module_exit(void)

{

  kfree(kmallocmem);

  vfree(vmallocmem);

}

module_init(mem_module_init);

module_exit(mem_module_exit);

 

總結:

a、kmalloc和vmalloc分配的是內(nèi)核的內(nèi)存,malloc分配的是用戶的內(nèi)存。

b、kmalloc保證分配的內(nèi)存在物理上是連續(xù)的, kmalloc()分配的內(nèi)存在0xBFFFFFFF-0xFFFFFFFF以上的內(nèi)存中,driver一般是用它來完成對DS的分配,更適合于類似設備驅(qū)動的程序來使用。

c、vmalloc保證的是在虛擬地址空間上的連續(xù),vmalloc()則是位于物理地址非連續(xù),虛地址連續(xù)區(qū),起始位置由VMALLOL_START來決定,一般作為交換區(qū)、模塊的分配。

d、kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相對較大(因為vmalloc還可以處理交換空間)。

e、內(nèi)存只有在要被DMA訪問的時候才需要物理上連續(xù),vmalloc比kmalloc要慢。

f、vmalloc使用的正確場合是分配一大塊,連續(xù)的,只在軟件中存在的,用于緩沖的內(nèi)存區(qū)域。不能在微處理器之外使用。

g、vmalloc 中調(diào)用了kmalloc (GFP—KERNEL),因此也不能應用于原子上下文。

hkmalloc和kfree管理內(nèi)核段內(nèi)分配的內(nèi)存,這是真實地址已知的實際物理內(nèi)存塊。

i、vmalloc對應于vfree,分配連續(xù)的虛擬內(nèi)存,但是物理上不一定連續(xù)。

j、kmalloc分配內(nèi)存是基于slab,因此slab的一些特性包括著色,對齊等都具備,性能較好。物理地址和邏輯地址都是連續(xù)的。