设备驱动程序常常会反复的分配很多相同大小的内存块;内核实现了后备高速缓存来对此进行支持,以反复的使用这些相同的内存块;
创建
Linux内核的高速缓存管理有时被称为“slab分配器”;因此,相关函数和类型在<linux/slab.h>中声明;slab分配器实现的告诉缓存具有kmem_cache类型;通过调用kmem_cache_create创建;
1 struct kmem_cache * 2 kmem_cache_create(const char *name, size_t size, size_t offset, 3 unsigned long flags, void (*ctor)(void *))
该函数创建一个新的高速缓存对象,其中可以容纳任意数目的内存区域,这些区域的大小相同,由size参数指定;
参数name与这个高速缓存相关联,其功能是保管一些信息以便追踪问题,它通常被设置为将要高速缓存的结构类型的名字;高速缓存保留指向该名称的指针,而不是复制其内容,因此,驱动程序应该指向静态存储的指针传递给这个函数,名称中不能包含空白;
参数offset是页面中第一个对象的偏移量,它可以用来确保对已分配的对象进行某种特殊对齐,但是最常用的就是0,表示使用默认值;
参数flags控制如何完成分配,是一个掩码,取值如下:
SLAB_NO_REAP-设置这个标志可以保护高速缓存在系统寻找内存的时候不会被减少;设置该标志通常不是好主意,我们不应该对内存分配器的自由做一些认为的,不必要的限制;
SLAB_HWCACHE_ALIGN-这个标志要求所有数据对象跟高速缓存行对齐;实际的操作则依赖于主机平台的硬件高速缓存布局;如果在SMP机器上,高速缓存中包含有频繁访问的数据项的话,则该选项将是非常好的选择;但是,为了满足高速缓存行对齐的需求,必要的填白可能浪费大量内存;
SLAB_CACHE_DMA-这个标志要求没给数据对象都从可用于DMA的内存区段中分配;
还有一些标志可用于高速缓存分配的调试,但通常这些标志值在开发系统中通过内核配置选项而全局地设置;
参数construtor是可选的,用于初始化新分配的对象;通常不使用,直接传递NULL;该函数在分配用于一组对象时调用,因为这些内容中可能包含好几个对象,所以constructor可能会被调用多次;我们不能认为分配一个对象之后随之就会调用一次constructor;
分配
一旦某个对象的高速缓存被创建,就可以调用kmem_cache_alloc从中分配内存对象:
1 void *kmem_cache_alloc(struct kmem_cache *cachep, int flags)
参数cache是先前创建的高速缓存;参数flags和传递给kmalloc的相同,并且当需要分配更多内存来满足kmem_cache_alloc时,高速缓存还会利用这个参数;
释放
释放一个内存对象使用kmem_cache_free:
1 void kmem_cache_free(struct kmem_cache *cachep, void *objp)
销毁
如果驱动程序代码和高速缓存有关的部分已经处理完了,这时驱动程序应该释放它的高速缓存;
1 void kmem_cache_destroy(struct kmem_cache *s)
这个参数只有在已经将缓存中分配的所有对象都归还后才能成功,所以,模块应该检查kmem_cache_destroy的返回状态;如果失败,则表明模块中发生了内存泄露;
使用后备高速缓存的另外一个好处是内核可以统计高速缓存的使用情况,高速缓存的使用统计可以从/proc/slabinfo获得;