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