浅析linux内核内存管理之内存池
2012-05-09 22:19
363 查看
内存池(memory pool)是linux 2.6的一个新特性。内核中有些地方的内存分配是不允许失败的。为了确保这种情况下的成功分配,内核开发者建立了一种称为内存池的抽象。内存池其实就是某种形式的后备高速缓存,它试图始终保存空闲的内存,以便在紧急状态下使用。下边是内存池对象的类型:
[cpp] view
plaincopy
typedef struct mempool_s {
spinlock_t lock; /*用来保护对象字段的自旋锁*/
int min_nr; /*内存池中元素的最大个数*/
int curr_nr; /*当前内存池中元素的个数*/
void **elements; /*指向一个数组的指针,该数组由指向保留元素的指针组成*/
void *pool_data; /*池的拥有者可获得的私有数据*/
mempool_alloc_t *alloc; /*分配一个元素的方法*/
mempool_free_t *free; /*释放一个元素的方法*/
wait_queue_head_t wait; /*当内存池为空时使用的等待队列*/
} mempool_t;
下面介绍一些API,这些API的内核源码不过二百多行:
创建内存池对象,mempool_create():
[cpp] view
plaincopy
mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn, mempool_free_t *free_fn, void *pool_data);
min_nr参数表示的是内存池应始终保持的已分配对象的最少数目,对象的实际分配和释放由alloc_fn和free_fn函数处理,其原型如下:
[cpp] view
plaincopy
typedef void *(mempool_alloc_t)(int gfp_mask, void *pool_data);
typedef void mempool_free_t(void *element, void *pool_data);
mempool_create的最后一个参数,即pool_data,被传入alloc_fn和free_fn。
在建立内存池之后,可如下所示分配和释放对象:
[cpp] view
plaincopy
void *mempool_alloc(mempool_t *pool, int gfp_mask);
void mempool_free(void *element, mempool_t *pool);
在创建mempool时,就会多次调用分配函数为预先分配的对象创建内存池,创建的对象个数为min_nr的大小。之后,对mempool_alloc()的调用将首先通过分配函数获得该对象;如果该分配失败,就会返回预先分配的对象(如果存在的话)。如果使用mempool_free释放一个对象,则如果预先分配的对象数目小于要求的最低数目,就会将该对象保留在内存池中;否则,该对象会返回给系统。
可以调用下面的函数来调整mempool的大小:
[cpp] view
plaincopy
int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask);
可以使用下面的函数将内存池返回给系统:
[cpp] view
plaincopy
void mempool_destroy(mempool_t *pool);
在销毁mempool之前,必须将所有已分配的对象返回到内存池中,否则会导致内核oops。
下边是自己编写的一个测试程序:
[cpp] view
plaincopy
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/mempool.h>
#include <linux/gfp.h>
#include <linux/delay.h>
struct my_mempool{
int val;
};
#define MY_MIN_MEMPOOL 20
struct kmem_cache * mempool_cachep = NULL;
mempool_t * my_pool = NULL;
struct my_mempool * mempool_object = NULL;
static int __init mempool_init(void){
printk("memory pool test module init!\n");
mempool_cachep = kmem_cache_create("mempool_cachep", sizeof(struct my_mempool), 0, 0, NULL);
if(!mempool_cachep)
return -ENOMEM;
my_pool = mempool_create(MY_MIN_MEMPOOL, mempool_alloc_slab, mempool_free_slab, mempool_cachep);
if(!my_pool)
return -ENOMEM;
mempool_object = (struct my_mempool *)mempool_alloc(my_pool, GFP_KERNEL);
if(mempool_object)
printk("one object has been allocated!\n");
else
goto fail;
printk("memory pool curr_nr is %d, min_nr is %d\n", my_pool->curr_nr, my_pool->min_nr);
mempool_free(mempool_object, my_pool);
return 0;
fail:
mempool_destroy(my_pool);
kmem_cache_destroy(mempool_cachep);
return -1;
}
static void __exit mempool_exit(void){
printk("memory pool test module exit!\n");
if(my_pool){
mempool_destroy(my_pool);
printk("mempool has been destroy!\n");
}
if(mempool_cachep){
kmem_cache_destroy(mempool_cachep);
printk("cache has been destroy!\n");
}
}
module_init(mempool_init);
module_exit(mempool_exit);
MODULE_AUTHOR("embeddedlwp@163.com");
MODULE_LICENSE("GPL");
这里创建了一个名为mempool_cachep的cache,然后又创建了一个memory pool,它的pool_data传的是指向cache的指针,表示这个memory pool是被用来保存slab对象的。这里分配一个object,然后cat /proc/slabinfo发现mempool_cachep的被使用object增加了1个,说明memory
pool并没有从自己的那20个object中取得对象,而是从slab对象的cache中。其实,memory pool就相当于一种家里攒点钱留着保命的策略,在cache里有对象的时候就从cache分配,如果cache没有空闲object了,会调用cache_grow()分配新的slab。如果连cache都无法从系统获得slab了,那才开始使用那些为了保命攒下的“钱”。memory pool使用的那20个object是从slab的cache中分配的,所以释放的时候,要现释放memory pool,这样那20个object才会释放回cache,然后cache没有对象被使用才可以正确的释放了。
[cpp] view
plaincopy
typedef struct mempool_s {
spinlock_t lock; /*用来保护对象字段的自旋锁*/
int min_nr; /*内存池中元素的最大个数*/
int curr_nr; /*当前内存池中元素的个数*/
void **elements; /*指向一个数组的指针,该数组由指向保留元素的指针组成*/
void *pool_data; /*池的拥有者可获得的私有数据*/
mempool_alloc_t *alloc; /*分配一个元素的方法*/
mempool_free_t *free; /*释放一个元素的方法*/
wait_queue_head_t wait; /*当内存池为空时使用的等待队列*/
} mempool_t;
下面介绍一些API,这些API的内核源码不过二百多行:
创建内存池对象,mempool_create():
[cpp] view
plaincopy
mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn, mempool_free_t *free_fn, void *pool_data);
min_nr参数表示的是内存池应始终保持的已分配对象的最少数目,对象的实际分配和释放由alloc_fn和free_fn函数处理,其原型如下:
[cpp] view
plaincopy
typedef void *(mempool_alloc_t)(int gfp_mask, void *pool_data);
typedef void mempool_free_t(void *element, void *pool_data);
mempool_create的最后一个参数,即pool_data,被传入alloc_fn和free_fn。
在建立内存池之后,可如下所示分配和释放对象:
[cpp] view
plaincopy
void *mempool_alloc(mempool_t *pool, int gfp_mask);
void mempool_free(void *element, mempool_t *pool);
在创建mempool时,就会多次调用分配函数为预先分配的对象创建内存池,创建的对象个数为min_nr的大小。之后,对mempool_alloc()的调用将首先通过分配函数获得该对象;如果该分配失败,就会返回预先分配的对象(如果存在的话)。如果使用mempool_free释放一个对象,则如果预先分配的对象数目小于要求的最低数目,就会将该对象保留在内存池中;否则,该对象会返回给系统。
可以调用下面的函数来调整mempool的大小:
[cpp] view
plaincopy
int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask);
可以使用下面的函数将内存池返回给系统:
[cpp] view
plaincopy
void mempool_destroy(mempool_t *pool);
在销毁mempool之前,必须将所有已分配的对象返回到内存池中,否则会导致内核oops。
下边是自己编写的一个测试程序:
[cpp] view
plaincopy
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/mempool.h>
#include <linux/gfp.h>
#include <linux/delay.h>
struct my_mempool{
int val;
};
#define MY_MIN_MEMPOOL 20
struct kmem_cache * mempool_cachep = NULL;
mempool_t * my_pool = NULL;
struct my_mempool * mempool_object = NULL;
static int __init mempool_init(void){
printk("memory pool test module init!\n");
mempool_cachep = kmem_cache_create("mempool_cachep", sizeof(struct my_mempool), 0, 0, NULL);
if(!mempool_cachep)
return -ENOMEM;
my_pool = mempool_create(MY_MIN_MEMPOOL, mempool_alloc_slab, mempool_free_slab, mempool_cachep);
if(!my_pool)
return -ENOMEM;
mempool_object = (struct my_mempool *)mempool_alloc(my_pool, GFP_KERNEL);
if(mempool_object)
printk("one object has been allocated!\n");
else
goto fail;
printk("memory pool curr_nr is %d, min_nr is %d\n", my_pool->curr_nr, my_pool->min_nr);
mempool_free(mempool_object, my_pool);
return 0;
fail:
mempool_destroy(my_pool);
kmem_cache_destroy(mempool_cachep);
return -1;
}
static void __exit mempool_exit(void){
printk("memory pool test module exit!\n");
if(my_pool){
mempool_destroy(my_pool);
printk("mempool has been destroy!\n");
}
if(mempool_cachep){
kmem_cache_destroy(mempool_cachep);
printk("cache has been destroy!\n");
}
}
module_init(mempool_init);
module_exit(mempool_exit);
MODULE_AUTHOR("embeddedlwp@163.com");
MODULE_LICENSE("GPL");
这里创建了一个名为mempool_cachep的cache,然后又创建了一个memory pool,它的pool_data传的是指向cache的指针,表示这个memory pool是被用来保存slab对象的。这里分配一个object,然后cat /proc/slabinfo发现mempool_cachep的被使用object增加了1个,说明memory
pool并没有从自己的那20个object中取得对象,而是从slab对象的cache中。其实,memory pool就相当于一种家里攒点钱留着保命的策略,在cache里有对象的时候就从cache分配,如果cache没有空闲object了,会调用cache_grow()分配新的slab。如果连cache都无法从系统获得slab了,那才开始使用那些为了保命攒下的“钱”。memory pool使用的那20个object是从slab的cache中分配的,所以释放的时候,要现释放memory pool,这样那20个object才会释放回cache,然后cache没有对象被使用才可以正确的释放了。
相关文章推荐
- 浅析linux内核内存管理之高端内存(上)
- 浅析linux内核内存管理之bootmem allocator
- 【C++内存管理】浅析C++中函数调用时的内存分配-函数调用过程中其他函数相关的内存分布
- 浅析linux内核内存管理之page allocator
- 浅析linux内核内存管理之kmalloc
- linux内核中内存管理数据结构关系及机制(原题:linux虚拟内存组织结构浅析)
- 内存管理器(十八)kernel 内存管理---浅析内存寻址
- Linux内核内存管理之内存结构概述(一)
- Nginx内存管理及数据结构浅析–共享内存的实现
- linux内核分析--浅析内存管理机制
- 浅析嵌入式系统中大量小块内存申请释放的内存管理方案
- 浅析linux内核内存管理之PAE
- linux内核高端内存管理之固定内存区与映射
- Linux内核内存管理-内存访问与缺页中断
- 浅析linux内核内存管理之buddy system
- 浅析linux内核内存管理之分页
- Nginx内存管理及数据结构浅析–共享内存的实现
- Linux内核-内存管理之高端内存
- linux内存管理--linux内核高端内存
- JVM内存结构浅析