kmalloc

Kmalloc內存分配和malloc相似,除非被阻塞否則他執行的速度非常快,而且不對獲得空間清零。

Flags參數

#include<linux/slab.h>

Void *kmalloc(size_t size, int flags);

第一個參數是要分配的塊的大小,第二個參數是分配標誌(flags),他提供了多種kmalloc的行爲。

最常用的GFP_KERNEL,他表示內存分配(最終總是調用get_free_pages來實現實際的分配,這就是,這就是GFP前綴的由來)是代表運行在內核空間的進程執行的。使用GFP_KERNEL容許kmalloc在分配空閒內存時候如果內存不足容許把當前進程睡眠以等待。因此這時分配函數必須是可重入的。如果在進程上下文之外如:中斷處理程序、tasklet以及內核定時器中這種情況下current進程不該睡眠,驅動程序該使用GFP_ATOMIC.

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 讀是有用的, 此時在處理器緩衝中出現是無用的. 一個完整的對如何分配 DMA 緩存的討論看"直接內存存取"一節在第 1 章.

__GFP_NOWARN

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

__GFP_HIGH

這個標誌標識了一個高優先級請求, 它被允許來消耗甚至被內核保留給緊急狀況的最後的內存頁.

__GFP_REPEAT

__GFP_NOFAIL

__GFP_NORETRY

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

 

2.內存區段

__GFP_DMA和__GFP_HIGHMEM的使用與平臺相關,Linux把內存分成3個區段:可用於DMA的內存、常規內存、以及高端內存。X86平臺上ISA設備DMA區段是內存的前16MB,而PCI設備無此限制。

內存區後面的機制在 mm/page_alloc.c 中實現, 而內存區的初始化在平臺特定的文件中, 常常在 arch 目錄樹的 mm/init.c。

Linux 處理內存分配通過創建一套固定大小的內存對象池. 分配請求被這樣來處理, 進入一個持有足夠大的對象的池子並且將整個內存塊遞交給請求者. 驅動開發者應當記住的一件事情是, 內核只能分配某些預定義的, 固定大小的字節數組.

如果你請求一個任意數量內存, 你可能得到稍微多於你請求的, 至多是 2 倍數量. 同樣, 程序員應當記住 kmalloc 能夠處理的最小分配是 32 或者 64 字節, 依賴系統的體系所使用的頁大小. kmalloc 能夠分配的內存塊的大小有一個上限. 這個限制隨着體系和內核配置選項而變化. 如果你的代碼是要完全可移植, 它不能指望可以分配任何大於 128 KB. 如果你需要多於幾個 KB, 但是, 有個比 kmalloc 更好的方法來獲得內存

 

 

在設備驅動程序或者內核模塊中動態開闢內存,不是用malloc,而是kmalloc ,vmalloc,或者用get_free_pages直接申請頁。釋放內存用的是kfree,vfree,或free_pages. kmalloc函數返回的是虛擬地址(線性地址). kmalloc特殊之處在於它分配的內存是物理上連續的,這對於要進行DMA的設備十分重要. 而用vmalloc分配的內存只是線性地址連續,物理地址不一定連續,不能直接用於DMA.

  注意kmalloc最大隻能開闢128k-16,16個字節是被頁描述符結構佔用了。kmalloc用法參見khg.

  內存映射的I/O口,寄存器或者是硬件設備的RAM(如顯存)一般佔用F0000000以上的地址空間。在驅動程序中不能直接訪問,要通過kernel函數vremap獲得重新映射以後的地址。

  另外,很多硬件需要一塊比較大的連續內存用作DMA傳送。這塊內存需要一直駐留在內存,不能被交換到文件中去。但是kmalloc最多隻能開闢大小爲32XPAGE_SIZE的內存,一般的PAGE_SIZE=4kB,也就是128kB的大小的內存。

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