Linux内核模块开发 Slab高速缓存接口与用例
在內核模塊開發或者驅動開發中經常會使用到內存分配,常見的方式是調用 kmalloc 接口分配內存。
static __always_inline void *kmalloc(size_t size, gfp_t flags);kmalloc接口使用簡單,并且不會對所獲取的空間清零,分配的空間仍然保持著原有的數據。但是根據<linux設備驅動程序>一書中的說法,kmalloc能夠分配的內存塊大小,存在一個上限。這個限制隨著體系架構的不同以及內核配置選項的不同而變化。此外,在程序中常常會反復分配很多同一大小的內存塊,經常會帶來重復初始化和內存碎片問題,于是內核提供了slab機制。
slab的優勢
與傳統的內存管理模式相比, slab 緩存分配器提供了很多優點。首先,內核通常依賴于對小對象的分配,它們會在系統生命周期內進行無數次分配。slab 緩存分配器通過對類似大小的對象進行緩存而提供這種功能,從而避免了常見的碎片問題。slab 分配器還支持通用對象的初始化,從而避免了為同一目而對一個對象重復進行初始化。最后,slab 分配器還可以支持硬件緩存對齊和著色,這允許不同緩存中的對象占用相同的緩存行,從而提高緩存的利用率并獲得更好的性能。
slab的接口簡單,包含slab緩存創建,對象內存分配、釋放與slab緩存銷毀。
/* 創建 slab 緩存結構 */ static struct kmem_cache *my_cachep;/* * slab 緩存創建 * 該函數創建一個新的高速緩存對象啊,其中可以容納任意數目的內存區域,這些區域的大小都相同,* 由size參數指定,參數name與這個高速緩存相關聯,其功能是保管一些信息以便跟蹤,它通常被* 設置為將要高速緩存的結構類型的名字,高速緩存保留指向該名稱的指針而不是復制其內容,因此* ,程序應該將指向靜態存儲的指針傳遞給這個函數。名稱中不能有空白。* align參數指的是某種對齊方式,通常取值為0* flag控制如何分配,是一個位掩碼,可以有如下取值:** SLAB_NO_RAP : 設置這個標志可以保護高速緩存在系統尋找內存的時候不會被減少,設置該標志通常不是* 好主意,因為對內存分配器的自由做一些人為的、不必要的限制。** SLAB_HWCACHE_ALIGN :* 這個標志要求所有數據對象跟高速緩存行對齊;實際的操作則依賴與主機平臺的硬件高速緩存布局,如果在* SMP機器上,高速緩存中包含有頻繁訪問的數據項的話,該選項是一個非常好的選擇,但是,為了滿足高速* 緩存行的對齊需求,必要的填白可能浪費大量內存。** 還有其它的一些選項,如SLAB_CACHE_DMA, SLAB_DESTROY_BY_RCU,SLAB_MEM_SPREAD* 具體使用哪一個根據應用決定,每個選項在源文件linux/slab.h中有詳細注釋*/ struct kmem_cache *kmem_cache_create (const char *name, size_t size, size_t align,unsigned long flags, void (*ctor)(void *))/** 從緩存中分配一個對象 * flag標志位常用的有GFP_KERNEL, GFP_ATOMIC,區別在于前者可能會引起睡眠*/ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags);/* 將一個對象釋放回slab */ void kmem_cache_free( struct kmem_cache *cachep, void *objp );/* 銷毀 slab 緩存, 調用前必須確保所有對象都已經返還給slab緩存 */ void kmem_cache_destroy(struct kmem_cache *cachep);/* 其它接口 */ //與kmem_cache_alloc類似,只不過它會對分配到的緩存清零 static inline void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags);下面是一個簡單的slab使用的demo,包括創建slab緩存, 分配對象內存,釋放對象與銷毀slab緩存。
/** Description : slab高速緩存用例* Author : mason* Date : 201809*/ #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h>#define log_info(fmt, arg...) printk("<3>%s:%d " fmt, __FUNCTION__ , __LINE__, ##arg)/* 創建slab 緩存結構 */ static struct kmem_cache *slab_cachep;static int __init slab_demo_init(void) {void *object;log_info("slab cache init \r\n");/* 創建slab緩存,對象大小32個字節 */slab_cachep = kmem_cache_create("slab_demo_cache", 32, 0, SLAB_DESTROY_BY_RCU, NULL);if (!slab_cachep){log_info("error, create slab_cache fail! \r\n");return -1;}/* 分配對象內存 */object = kmem_cache_alloc(slab_cachep, GFP_KERNEL); if (object) {log_info("create slab object success \r\n");kmem_cache_free( slab_cachep, object );}return 0; }static void __exit slab_demo_exit(void) {kmem_cache_destroy( slab_cachep );log_info("slab cache destroy \r\n"); }module_init(slab_demo_init); module_exit(slab_demo_exit); MODULE_LICENSE("GPL");內核版本 3.4.39
運行截圖:
參考資料:
1.?Linux slab 分配器剖析?:
https://www.ibm.com/developerworks/cn/linux/l-linux-slab-allocator/
2. 《linux設備驅動程序第三版》
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Linux内核模块开发 Slab高速缓存接口与用例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是政治站位高(什么是政治站位)
- 下一篇: 10转4股派20元是什么意思?