Chinaunix首页 | 论坛 | 博客
  • 博客访问: 285056
  • 博文数量: 49
  • 博客积分: 3083
  • 博客等级: 中校
  • 技术积分: 710
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-27 08:22
文章分类

全部博文(49)

文章存档

2009年(8)

2008年(41)

分类: LINUX

2008-12-11 11:04:46

 

在内核中的一些地方,内存的分配不允许失败,为了确保内存的成功分配,内核开发者创建了一个叫做内存池的东西.

内存池的类型为struct mempool_s详细定义如下:

typedef struct mempool_s {

         spinlock_t lock;

         int min_nr;                 /* nr of elements at *elements */

         int curr_nr;                /* Current nr of elements at *elements */

         void **elements;

 

         void *pool_data;

         mempool_alloc_t *alloc;

         mempool_free_t *free;

         wait_queue_head_t wait;

} mempool_t;

 

创建一个内存池需要一个mempool_t *mempool_create()
跟踪代码可以知道,其实该函数是调用mempool_create_node(min_nr,alloc_fn,free_fn, pool_data,-1)来实现内存池的创建.
mempool_create_node()的工作流程如下:
1、通过kmallocpool->kmalloc_node分配内存,失败则清空pool,返回null
2、开启pool->lock的自旋锁,pool->min_nrpool->pool_data分别赋值为min_nrpool_data
3、初始化pool->wait等待队列,将pool->alloc  pool->free 的值设置成free_fnalloc_fn
4、pool->curr_nr小于pool->min_nr时,循环将pool->alloc的值交给element,当pool->alloc分配失败时释放掉当前的内存池,返回null,把刚得到的element加入pool中。
5、返回最终得到的内存池
 
 
mempool_alloc负责分配创建得到的内存池分配
1、查看gfp的标志是否允许睡眠
2、设置gfp标志为__GFP_NOMEMALLOC(不分配紧急储备)__GFP_NORETRY(不在__alloc_pages中循环使用)__GFP_NOWARN(取消警告信息)
3、将当前gfp标志并上__GFP_WAIT__GFP_IO的补码,设置成一个临时变量gfp_temp
4、pool->alloc分配得到的mempool_alloc_t交给element,如果分配成功,返回element
5、Pool->alloc获得自旋锁,并在此之前禁止中断
6、如果pool->curr_nrb不为0时,将pool->element[curr_nr-1]在减除自旋锁之后返回
7、解除自旋锁
8、如果gfp没有__GFP_WAIT标志,返回null
9、gfp_mask在此赋值给gfp_temp
10、  初始化等待队列wait,并将其加入pool->wait
11、  加入内存屏障
12、  如果pool->curr_nr0时,设置5秒的读写调度超时,
13、  删除wait中的等待队列,再次从第四步开始重新分配
 
 
在当前内存池的大小不合适的情况下,可以采用mempool_resize()来重新设置min_nr的值
1、开启自旋锁pool->lock,并且在开启之前禁止中断
2、如果新的min_nr小于等于当前的min_nr时,释放pool->element的最后一个元素后退出,中间有个关闭开启自旋锁的过程,重新设置min_nr的值之后释放自旋锁退出
3、释放掉自旋锁
4、重新调用kmalloc分配内存交给new_element,分配失败时,返回-ENOMEM
5、开启自旋锁
6、当新min_nr大于min_nr时,释放掉刚分配的内存返回0
7、关闭自旋锁,允许内存池增加
8、pool->element大小为pool->curr_nr * sizeof(*new_elements)的复制到new_element,也就是全部的复制
9、释放掉以前的pool->element
10、  new_element设置成pool->element,将new_min_nr的值赋值给pool->min_nr
11、  curr_nr小于min_nr时,循环执行:
a)   释放自旋锁
b)   pool->alloc新分配空间交给element,失败则返回0
c)   加上自旋锁,当curr_nr小于min_nr时,加入elementpool否则,解除自旋锁,释放掉刚申请的element,返回0
 
 
 
阅读(2379) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~