kzalloc和kmalloc函式詳解

2021-07-02 06:31:34 字數 3970 閱讀 9074

用kzalloc申請記憶體的時候,

效果等同於先是用

kmalloc()

申請空間

,然後用

memset()

來初始化

,所有申請的元素都被初始化為

0.view plain

/*** kzalloc - allocate memory. the memory is set to zero.

* @size: how many bytes of memory are required.

* @flags: the type of memory to allocate (see kmalloc).

*/static

inline 

void

*kzalloc(size_t size, gfp_t flags)    

kzalloc 函式是帶引數呼叫kmalloc函式,新增的引數是或了標誌位__gfp_zero,

view plain

void

*__kmalloc(size_t size, gfp_t flags)    

這個函式呼叫trace_kmalloc,flags引數不變,繼續往裡面可以看到

view plain

static

__always_inline 

void

*slab_alloc(

struct

kmem_cache *s,  

gfp_t gfpflags, int

node, unsigned 

long

addr)  

local_irq_restore(flags);  

if(unlikely((gfpflags & __gfp_zero) && 

object

))  

memset(object

, 0, objsize);  

kmemcheck_slab_alloc(s, gfpflags, object

, c->objsize);  

kmemleak_alloc_recursive(object

, objsize, 1, s->flags, gfpflags);  

return

object

;  }  

這裡主要判斷兩個標誌,wait和zero,和本文有關的關鍵**就是

if (unlikely((gfpflags & __gfp_zero) && object))

memset(object, 0, objsize);

到此,這個函式區別於kmalloc的地方就清楚了

kmalloc 函式詳解

#include void *kmalloc(size_t size, int flags);

給 kmalloc 的第乙個引數是要分配的塊的大小. 第 2 個引數, 分配標誌, 非常有趣, 因為它以幾個方式控制 kmalloc 的行為.

最一般使用的標誌, gfp_kernel, 意思是這個分配((內部最終通過呼叫 __get_free_pages 來進行, 它是 gfp_ 字首的**) 代表執行在核心空間的程序而進行的. 換句話說, 這意味著呼叫函式是代表乙個程序在執行乙個系統呼叫. 使用 gfp_kenrl 意味著 kmalloc 能夠使當前程序在少記憶體的情況下睡眠來等待一頁. 乙個使用 gfp_kernel 來分配記憶體的函式必須, 因此, 是可重入的並且不能在原子上下文中執行. 當當前程序睡眠, 核心採取正確的動作來定位一些空閒記憶體, 或者通過重新整理快取到磁碟或者交換出去乙個使用者程序的記憶體.

gfp_kernel 不一直是使用的正確分配標誌; 有時 kmalloc 從乙個程序的上下文的外部呼叫. 例如, 這類的呼叫可能發生在中斷處理, tasklet, 和核心定時器中. 在這個情況下, 當前程序不應當被置為睡眠, 並且驅動應當使用乙個 gfp_atomic 標誌來代替. 核心正常地試圖保持一些空閒頁以便來滿足原子的分配. 當使用 gfp_atomic 時, kmalloc 能夠使用甚至最後乙個空閒頁. 如果這最後乙個空閒頁不存在, 但是, 分配失敗.

其他用來代替或者增添 gfp_kernel 和 gfp_atomic 的標誌, 儘管它們 2 個涵蓋大部分裝置驅動的需要. 所有的標誌定義在 , 並且每個標誌用乙個雙下劃線做字首, 例如 __gfp_dma. 另外, 有符號代表常常使用的標誌組合; 這些缺乏字首並且有時被稱為分配優先順序. 後者包括:

gfp_atomic

用來從中斷處理和程序上下文之外的其他**中分配記憶體. 從不睡眠.

gfp_kernel

核心記憶體的正常分配. 可能睡眠.

gfp_user

用來為使用者空間頁來分配記憶體; 它可能睡眠.

gfp_highuser

如同 gfp_user, 但是從高階記憶體分配, 如果有. 高階內存在下乙個子節描述.

gfp_noio

gfp_nofs

這個標誌功能如同 gfp_kernel, 但是它們增加限制到核心能做的來滿足請求. 乙個 gfp_nofs 分配不允許進行任何檔案系統呼叫, 而 gfp_noio 根本不允許任何 i/o 初始化. 它們主要地用在檔案系統和虛擬記憶體**, 那裡允許乙個分配睡眠, 但是遞迴的檔案系統呼叫會是乙個壞注意.

上面列出的這些分配標誌可以是下列標誌的相或來作為引數, 這些標誌改變這些分配如何進行:

__gfp_dma

這個標誌要求分配在能夠 dma 的記憶體區. 確切的含義是平台依賴的並且在下面章節來解釋.

__gfp_highmem

這個標誌指示分配的記憶體可以位於高階記憶體.

__gfp_cold

正常地, 記憶體分配器盡力返回"緩衝熱"的頁 -- 可能在處理器緩衝中找到的頁. 相反, 這個標誌請求乙個"冷"頁, 它在一段時間沒被使用. 它對分配頁作 dma 讀是有用的, 此時在處理器緩衝中出現是無用的.

__gfp_nowarn

這個很少用到的標誌阻止核心來發出警告(使用 printk ), 當乙個分配無法滿足.

__gfp_high

這個標誌標識了乙個高優先順序請求, 它被允許來消耗甚至被核心保留給緊急狀況的最後的記憶體頁.

__gfp_repeat

__gfp_nofail

__gfp_noretry

這些標誌修改分配器如何動作, 當它有困難滿足乙個分配. __gfp_repeat 意思是" 更盡力些嘗試" 通過重複嘗試 -- 但是分配可能仍然失敗. __gfp_nofail 標誌告訴分配器不要失敗; 它盡最大努力來滿足要求. 使用 __gfp_nofail 是強烈不推薦的; 可能從不會有有效的理由在乙個裝置驅動中使用它. 最後, __gfp_noretry 告知分配器立即放棄如果得不到請求的記憶體.

kmalloc 能夠分配的記憶體塊的大小有乙個上限. 這個限制隨著體系和核心配置選項而變化. 如果你的**是要完全可移植, 它不能指望可以分配任何大於 128 kb. 如果你需要多於幾個 kb

這方面的原因:

kmalloc並不直接從分頁機制中獲得空閒頁面而是從slab頁面分配器那兒獲得需要的頁面,slab的實現**限制了最大分配的大小為128k,即131072bytes,理論上你可以通過更改slab.c中的 cache_sizes陣列中的最大值使得kmalloc可以獲得更大的頁面數,不知道有沒有甚麼副效應或者沒有必要這樣做,因為獲取較大記憶體的方法有很多,想必128k是經驗總結後的合適值。

alloc_page( )可以分配的最大連續頁面是4k

static inline struct page * alloc_pages(unsigned int gfp_mask, unsigned int order) 

alloc_pages最大分配頁面數為512個,則可用記憶體數最大為2^9*4k=2m

kzalloc與kmalloc區別 核心函式

這個函式就是原來的兩個函式的整合 即原來我們每次申請記憶體的時候都會這麼做 先是用 kmalloc 申請空間 然後用 memset 來初始化 而現在省事了 一步到位 直接呼叫 kzalloc 效果等同於原來那兩個函式 所有申請的元素都被初始化為 0.其實對寫驅動的來說 知道現在應該用 kzalloc...

kzalloc 函式詳解

用kzalloc申請記憶體的時候,效果等同於先是用 kmalloc 申請空間 然後用 memset 來初始化 所有申請的元素都被初始化為 0.kzalloc allocate memory.the memory is set to zero.size how many bytes of memory...

kzalloc 函式詳解

用kzalloc申請記憶體的時候,效果等同於先是用 kmalloc 申請空間 然後用 memset 來初始化 所有申請的元素都被初始化為 0.csharp view plain copy kzalloc allocate memory.the memory is set to zero.size h...