kmem_cache_create
struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align,
unsigned long flags, void (*ctor)(void*),
void (*dtor)(void*));
参数解释:
const char *name: 缓存的名字,这个字符串会在/proc/slabinfo等内核调试信息中显示。
size_t size: 对象的大小,即缓存中每个对象所占的字节数。
size_t align: 对齐要求,指明对象在内存中的对齐粒度,通常是为了满足特定硬件或协议的要求。
unsigned long flags: 一组标志位,用来控制slab的行为,如SLAB_HWCACHE_ALIGN、SLAB_PANIC、SLAB_RECLAIM_ACCOUNT等。
void (*ctor)(void*): 可选的构造函数,如果提供,当从缓存分配一个新的对象时,会调用该函数初始化新对象的内容。
详细说明:
一种内核内存管理机制,特别针对小对象的高效分配和释放设计。
kmem_cache_create 函数创建的并不是一个具体的内存缓存对象,而是创建了一个用于管理固定大小内存块的slab缓存控制器。这个控制器(即kmem_cache结构体)是用来组织和分配多个相同大小的对象。
当调用 kmem_cache_create 时,您需要指定 size_t size 参数,这个参数指定了将来从该缓存分配出的每个对象的实际大小。因此,你不能直接说 kmem_cache_create 创建的内存缓存对象大小是多少,而应该说通过调用此函数并传入特定大小值后,可以用来分配相应大小的对象。例如,如果传给 size 的参数是512字节,则此slab缓存将用于分配大小为512字节的对象。
调用 kmem_cache_create 创建的slab缓存控制器,可以通过cat /proc/slab 来查看
kmem_cache_destroy
kmem_cache_create 对应的释放函数
代码示例:
#include <linux/slab.h>
static void my_ctor(void *ptr) {
// 初始化对象
}
static void my_dtor(void *ptr) {
// 清理对象
}
struct kmem_cache *my_cache;
static int __init my_init(void)
{
my_cache = kmem_cache_create("my_cache", sizeof(struct my_struct),
__alignof__(struct my_struct),
SLAB_HWCACHE_ALIGN | SLAB_PANIC,
my_ctor, my_dtor);
if (!my_cache) {
return -ENOMEM;
}
// 其他初始化操作...
return 0;
}
module_init(my_init);
static void __exit my_exit(void)
{
kmem_cache_destroy(my_cache); // 在模块退出时销毁缓存
}
module_exit(my_exit);
通过调用 kmem_cache_create() 创建缓存后,就可以使用 kmem_cache_alloc() 和 kmem_cache_free() 来快速地分配和释放这些类型的内存块。这有助于减少因频繁分配和释放小对象而带来的系统开销。
kmem_cache_alloc 和 kmem_cache_free
void *kmem_cache_alloc(struct kmem_cache * cachep, gfp_t flags);
参数解释:
struct kmem_cache * cachep: 由 kmem_cache_create() 创建的slab缓存指针。
gfp_t flags: 分配时使用的标志,用于控制如何进行内存分配以及在何种情况下可以阻塞等待内存可用。常见的标志包括但不限于:
GFP_KERNEL:用于正常运行时分配,可能会睡眠(不能在中断上下文或原子上下文中使用)。
GFP_ATOMIC:用于不能睡眠的情况,如中断处理程序、软中断或者tasklet中。
GFP_NOIO:禁止分配过程中执行任何I/O操作。
GFP_NOWAIT:同GFP_ATOMIC类似,不过不是所有的内存区域都支持此标志。
GFP_HIGHUSER、GFP_USER等:用于用户空间映射的内存分配。
例程:
#include <linux/slab.h>
struct my_struct;
static struct kmem_cache *my_cache;
// 假设my_cache已经通过kmem_cache_create创建好
struct my_struct *alloc_my_struct(void) {
struct my_struct *obj = NULL;
obj = kmem_cache_alloc(my_cache, GFP_KERNEL); // 或者根据需要选择合适的gfp_t标志
if (!obj) {
printk(KERN_ERR "Failed to allocate memory from cache\n");
return NULL;
}
// 对新分配的对象进行初始化...
return obj;
}
void free_my_struct(struct my_struct *obj) {
kmem_cache_free(my_cache, obj);
}
代码示例
// drivers/dma/ioat/init.c
...
1391 static int __init ioat_init_module(void)
1392 {
1393 int err = -ENOMEM;
1394
1395 pr_info("%s: Intel(R) QuickData Technology Driver %s\n",
1396 DRV_NAME, IOAT_DMA_VERSION);
1397
1398 ioat_cache = kmem_cache_create("ioat", sizeof(struct ioat_ring_ent),
1399 0, SLAB_HWCACHE_ALIGN, NULL);
1400 if (!ioat_cache)
1401 return -ENOMEM;
1402
1403 ioat_sed_cache = KMEM_CACHE(ioat_sed_ent, 0);
1404 if (!ioat_sed_cache)
1405 goto err_ioat_cache;
1406
1407 err = pci_register_driver(&ioat_pci_driver);
1408 if (err)
1409 goto err_ioat3_cache;
1410
1411 return 0;
1412
1413 err_ioat3_cache:
1414 kmem_cache_destroy(ioat_sed_cache);
1415
1416 err_ioat_cache:
1417 kmem_cache_destroy(ioat_cache);
1418
1419 return err;
1420 }
1421 module_init(ioat_init_module);
1422
1423 static void __exit ioat_exit_module(void)
1424 {
1425 pci_unregister_driver(&ioat_pci_driver);
1426 kmem_cache_destroy(ioat_cache);
1427 }
1428 module_exit(ioat_exit_module);
134 /*
135 * Please use this macro to create slab caches. Simply specify the
136 * name of the structure and maybe some flags that are listed above.
137 *
138 * The alignment of the struct determines object alignment. If you
139 * f.e. add ____cacheline_aligned_in_smp to the struct declaration
140 * then the objects will be properly aligned in SMP configurations.
141 */
142 #define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\
143 sizeof(struct __struct), __alignof__(struct __struct),\
144 (__flags), NULL)
//drivers/dma/ioat/prep.c
91 static struct ioat_sed_ent *
92 ioat3_alloc_sed(struct ioatdma_device *ioat_dma, unsigned int hw_pool)
93 {
94 struct ioat_sed_ent *sed;
95 gfp_t flags = __GFP_ZERO | GFP_ATOMIC;
96
97 sed = kmem_cache_alloc(ioat_sed_cache, flags);
98 if (!sed)
99 return NULL;
100
101 sed->hw_pool = hw_pool;
102 sed->hw = dma_pool_alloc(ioat_dma->sed_hw_pool[hw_pool],
103 flags, &sed->dma);
104 if (!sed->hw) {
105 kmem_cache_free(ioat_sed_cache, sed);
106 return NULL;
107 }
108
109 return sed;
110 }
1644



被折叠的 条评论
为什么被折叠?



