記憶體配置方法 kmalloc()、vmalloc()、__get_free_pages()

來源:互聯網
上載者:User

標籤:

Copyright: 該文章著作權由潘雲登所有。可在非商業目的下任意傳播和複製。

對於商業目的下對本文的任何行為需經作者同意。

 

 

 

kmalloc

#include <linux/slab.h>

void *kmalloc(size_t size, int flags);

void kfree(const void *ptr);

使用kmalloc可以獲得以位元組為單位的一塊核心記憶體,它不對所擷取的記憶體空間清零。這個函數返回一個指向記憶體塊的指標,其記憶體塊至少要有size大小。所分配的記憶體區在物理上是連續的。在出錯時,它返回NULL。因此,在調用kmalloc()後,必須檢查返回的是不是NULL。由kmalloc分配的記憶體,使用kfree方法進行釋放。

kmalloc的第一個參數是要分配塊的大小,第二個參數是分配器標誌。這個標誌在<linux/gfp.h>檔案中聲明,可以分為三類:行為修飾符、區修飾符以及類型標識。行為修飾符表示核心應當如何分配所需的記憶體,主要有:

__GFP_WAIT    分配器可以休眠

__GFP_HIGH    分配器可以訪問緊急事件緩衝池

__GFP_IO       分配器可以啟動磁碟I/O

__GFP_FS       分配器可以開機檔案系統I/O

區修飾符表示從哪裡分配記憶體:可用於DMA的記憶體(__GFP_DMA)、常規記憶體以及高端記憶體(__GFP_HIGHMEM)。類型標誌組合了行為修飾符和區修飾符,將各種可能用到的組合歸納為不同類型,簡化了修飾符的使用。因此,最常使用的flags參數為GFP_KERNEL和GFP_ATOMIC。後者用在中斷處理常式或其它運行於進程上下文之外的代碼中,這時kmalloc方法不會休眠。

#include <linux/gfp.h>

#define GFP_KERNEL         (__GFP_WAIT | __GFP_IO | __GFP_FS)

#define GFP_ATOMIC        (__GFP_HIGH)

實際上,kmalloc是建立在後面介紹的後備快取之上的。因此,核心只能分配一些預定義的、固定大小的位元組數組。根據當前體繫結構使用的頁面大小,kmalloc能處理的最小記憶體塊是32或者64。如果希望代碼具有完整的可移植性,則不應該分配大於128KB的記憶體。

樣本:

char *buf;

 

buf = kmalloc(BUF_SIZE, GFP_ATOMIC);

if (!buf)

/* 記憶體配置出錯! */

 

kfree(buf);

 

 

 

後備快取

分配和釋放資料結構是所有核心中最普遍的操作之一。為了便於資料的頻繁分配和回收,核心提供了後備快取機制,稱為“slab分配器”。slab分配器實現的快取具有kmem_cache_t類型,可通過調用kmem_cache_create建立。

#include <linux/slab.h>

kmem_cache_t *kmem_cache_create(const char *name, size_t size,

                                size_t offset,

                                unsigned long flags,

                                void (*constructor)(void *, kmem_cache_t *, unsigned long flags),

                                void (*destructor)(void *, kmem_cache_t *, unsigned long flags));

參數name存放快取的名字。size是快取中每個元素的大小。offset是快取中第一個對象的位移,用來確保在頁內進行特定的對齊,一般取0。flags是一個位元遮罩,用來控制快取的行為。constructor和destructor為快取的構造和解構函式,分別在新頁追加到快取和從快取中刪去頁時調用,通常取NULL。kmem_cache_create在成功時返回一個指向所建立快取的指標,否則,返回NULL。在建立快取後,使用kmem_cache_alloc從中分配記憶體對象。釋放一個記憶體對象時使用kmem_cache_free。要銷毀一個快取,則調用kmem_cache_destroy。

void *kmem_cache_alloc(kmem_cache_t *cache, int flags);

void kmem_cache_free(kmem_cache_t *cache, const void *obj);

int kmem_cache_destroy(kmem_cache_t *cache);

樣本:

kmem_cache_t *task_struct_cachep;

 

/*建立快取,SLAB_PANIC標誌在分配失敗時提醒slab層,

如果沒有提供SLAB_PANIC 標誌,必須自己檢查傳回值*/

task_struct_cachep = kmem_cache_create("task_struct",

sizeof(struct task_struct),

ARCH_MIN_TASKALIGN,

SLAB_PANIC,

NULL,

NULL);

 

/*分配記憶體對象*/

struct task_struct *tsk;

tsk = kmem_cache_alloc(task_struct_cachep, GFP_KERNEL);

if (!tsk)

return NULL;

 

/*釋放記憶體對象*/

kmem_cache_free(task_struct_cachep, tsk);

 

/*撤銷快取*/

int err;

err = kmem_cache_destroy(task_struct_cachep);

if (err)

/*撤銷快取出錯*/

 

 

 

 

分配頁

如果模組需要分配大塊的記憶體,使用面向頁的分配技術會更好些。分配頁面可以使用下面的函數:

#include <linux/gfp.h>

unsigned long get_zeroed_page(unsigned int gfp_mask);

unsigned long __get_free_page(unsigned int gfp_mask);

unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order);

它們返回記憶體地區第一個位元組的指標。其中,get_zeroed_page將分配所得的分頁清空。參數gfp_mask為分配器標誌,與kmaloc中的一樣。參數order是要分配的頁面數的以2為底的對數。當用位元組表示記憶體大小時,需要使用get_order函數進行轉換,而不應該對頁面大小進行任何假設,如:

#include <asm/page.h>

 

/*驅動程式需要16KB空間*/

/* get_order的參數必須是2的冪*/

int order = get_order(16*1024);

buf = get_free_pages(GFP_KERNEL, order);

當程式不再需要使用頁面時,可以使用下列函數進行釋放:

void free_page(unsigned long addr);

void free_pages(unsigned long addr, unsigned long order);

樣本:

unsigned long page;

 

page = __get_free_pages(GFP_KERNEL, 3);

if (!page) {

/*沒有足夠的記憶體,你必須處理這種錯誤! */

return ENOMEM;

}

 

/* ‘page‘現在指向8個連續頁中第1個頁的地址*/

 

free_pages(page, 3);

 

 

 

vmalloc

#include <linux/vmalloc.h>

void * vmalloc(unsigned long size);

void vfree(void *addr);

vmalloc函數的工作方式類似於kmalloc,只不過前者分配的記憶體虛擬位址是連續的,而物理地址則無需連續。它通過分配非連續的實體記憶體塊,再修改頁表,把記憶體映射到邏輯地址空間的連續地區中。通過vmalloc獲得的頁必須一個一個地進行映射,效率不高,因此,只在不得已(一般是為了獲得大塊記憶體)時使用。vmalloc函數返回一個指標,指向邏輯上連續的一塊記憶體區,其大小至少為size。在發生錯誤時,函數返回NULL。vmalloc可能睡眠,因此,不能從中斷上下文中進行調用,也不能從其它不允許阻塞的情況下調用。要釋放通過vmalloc所獲得的記憶體,應使用vfree函數。

樣本:

char *buf;

 

buf = vmalloc(16 * PAGE_SIZE); /*獲得16頁*/

if (!buf)

/*錯誤,不能分配記憶體*/

 

vfree(buf);

記憶體配置方法 kmalloc()、vmalloc()、__get_free_pages()

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.