linux kernel中
memory可以分成3種類型的ZONE
1. ZONE_DMA: 有些Device需要用DMA (direct memory access) 用途的memory
2. ZONE_NORMAL: 一般memory
3. ZONE_HIGHMEM: high memory, 不是永久都會是kernel space address的那些memory
在linux kernel中allocate page or memory的function
1. struct page * alloc_pages(gfp_t gfp_mask, unsigned int order)
gfp_mask 待會再說 先感受一下page要怎樣allocate
要注意的是,這裡的order指的是 2^order (1 << order)
例如
page = alloc_pages(GFP_KERNEL, 2);
要的是4個page
另 page_address(struct page *page) 可以回傳page的logical address
2. unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
這個function的動作和alloc_pages()一樣,只是他是直接回傳page的logical address
3. struct page * alloc_page(gfp_t gfp_mask)
等同於
alloc_pages(gfp_mask, 0);
4. unsigned long __get_free_page(gfp_t gfp_mask)
等同於
__get_free_pages(gfp_mask, 0);
5. unsigned long get_zeroed_page(unsigned int gfp_mask)
這個function比較特別,回傳的是page 的logical address
但是內容已經被清為0
注意 以上function回傳的都是連續的physical space (連續的physical pages)!!
對應的free functions
void __free_pages(struct page *page, unsigned int order)
void free_pages(unsigned long addr, unsigned int order)
void free_page(unsigned long addr)
記住!
在alloc memory的時候必須加入錯誤偵測
因為並不一定每一次alloc memory 都會成功
sample code.
unsigned long page;
page = __get_free_pages(GFP_KERNEL, 3)
if (!page) {
/* 記憶體不足 */
return -ENOMEM;
}
/* 不需要用 請記得釋放它 */
free_pages(page, 3)
以上所說 都為page為單位
以下是以byte為單位
1. void * kmalloc(size_t size, gfp_t flags);
void kfree(const void *ptr);
回傳一個連續的physical space
Sample code.
struct dog *p;
p = kmalloc(sizeof(struct dog), GFP_KERNEL);
if (!p)
/* handling error... */
kfree(p);
很明顯的 這個function所回傳的資料
最小一定會比size大 這是因為kernel的最底層
會是以page為單位allocate
所以回傳的大小會是page size的倍數
注意!!
不用要kfree()去釋放不是由kmalloc()所配置的memory
剛剛用了這麼多gfp_mask
現在深入的談談gfp_mask 有哪些flag 和 要怎麼用
是可以分成action modifier, zone modifier, 和type flag
不過一般來說只會用到type flag
type flag是由action modifier和zone modifier組成
但是在這裡只會紀錄常用的type flag
Type Flags
1. GFP_ATOMIC
一看見atomic 然後去查字典 會發現是原子的意思
原子跟kernel 有甚麼關係 ??
其實應該是取他不可分割的意思
意思就是這個動作不會被中斷 一次做到完的意思
在alloc memory的時候 為了要回收memory可能會reschedule
會造成這個process sleep
所以這個flag就是確保在allocate memory的時候不會做以上的動作
這個特性 就是要用在
interrupt handles 之類,不能sleep的routine中
2. GFP_KERNEL
可以進入sleep,最常用的應該就是這個flag
如果沒有特殊需求 用這個就對了
3. GFP_NOIO, GFP_NOFS
NOIO 沒有初始化disk I/O
NOFS 沒有初始化filesystem I/O
為什麼需要用??
I/O只有一個
假設沒有使用這些flag
第一個allocator 配置memory 做了I/O的操作
另一個allocator 配置memory的時候也做了I/O的動作
allocator必需確認沒有人在使用I/O
會造成deadlock
4. GFP_DMA
通常使用在device drivers 而且和GFP_ATOMIC 或 GFP_KERNEL
其中之一連用
以下是一些情況和對應的flags
-------------------------------------------------------------
情況 flags
process context, can sleep Use GFP_KERNEL
process context, cannot sleep Use GFP_ATOMIC
interrupt handler Use GFP_ATOMIC
softirq Use GFP_ATOMIC
tasklet Use GFP_ATOMIC
need DMA memory, can sleep Use (GFP_DMA | GFP_KERNEL)
need DMA memory, cannot sleep Use (GFP_DMA | GFP_ATOMIC)
另外 virtual address的配置是使用
vmalloc vfree
vmalloc()只保證回傳連續的virtual pages
在virtual address 是連續的!
在kernel中為了效能
通常都會使用kmalloc
Reference
- Oct 30 Sun 2011 14:47
[Linux] Linux Kernel Memory Allocation
全站熱搜
留言列表
發表留言