Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3892196
  • 博文数量: 146
  • 博客积分: 3918
  • 博客等级: 少校
  • 技术积分: 8585
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-17 13:52
个人简介

个人微薄: weibo.com/manuscola

文章分类

全部博文(146)

文章存档

2016年(3)

2015年(2)

2014年(5)

2013年(42)

2012年(31)

2011年(58)

2010年(5)

分类:

2011-05-22 01:08:08

#define ALLOC_NO_WATERMARKS 0x01 /* don't check watermarks at all */
#define ALLOC_WMARK_MIN 0x02 /* use pages_min watermark */
#define ALLOC_WMARK_LOW 0x04 /* use pages_low watermark */
#define ALLOC_WMARK_HIGH 0x08 /* use pages_high watermark */
#define ALLOC_HARDER 0x10 /* try to alloc harder */
#define ALLOC_HIGH 0x20 /* __GFP_HIGH set */
#define ALLOC_CPUSET 0x40 /* check for correct cpuset */
-------------------------------------------------------------------------
上述是一些标志位。用来控制内存的分配行为。
1)
#define ALLOC_WMARK_HIGH 0x08 /* use pages_high watermark */
只有内存域的页面数至少为zone->pages_high 才分配页面
2)
#define ALLOC_WMARK_LOW 0x04 /* use pages_low watermark */
只有内存域的页面数至少为zone->pages_low 才分配页面
3)
#define ALLOC_WMARK_MIN 0x02 /* use pages_min watermark */
只有内存域的页面数至少为zone->pages_min 才分配页面
4)
#define ALLOC_NO_WATERMARKS 0x01 /* don't check watermarks at all */
顾名思义,不需要考虑内存域的水位情况。
5)
#define ALLOC_HARDER 0x10 /* try to alloc harder */
这个标志位的含义是通知伙伴系统放宽限制。
代码中有如下
            long min = mark;
    if (alloc_flags & ALLOC_HARDER)
min -= min / 4;
6)
#define ALLOC_HIGH 0x20 /* __GFP_HIGH set */
在分配高端内存域时,进一步放宽限制
代码中有如下:
   if (alloc_flags & ALLOC_HIGH)
min -= min / 2;
----------------------------------------------------------------------------
继续关注 zone_water_mark_ok 这个函数之前,我们需要讲述清楚
1 zone->pages_min
2 zone->pages_low
3 zone->pages_high

page_min page_low page_high是内存域 zone这个结构体的成员变量,是页换出时使用的
水印。如果内存不足,内核将页换出,写入到硬盘上。这三个变量的值指导着交换守护进程
的行为:
1 如果内存域的空闲页面大于 pages_high,表示内存域的状态很好
2 如果内存域的空闲页面低于 pages_low,则内核需要将页换出到硬盘
3 如果内存域的空闲页面低于pages_min,则内存域中空闲页面太少,继续空闲页,页回收工作压力大。

接下来的问题是,如何计算内存域 水印的大小
计算水印之前,首先介绍全局变量 min_free_kbytes  这个值是需要为关键性分配保留的内存空间的最小值,
不能低于128K,不能高于64M,在函数init_per_zone_pages_min 中计算
代码如下
lowmem_kbytes = nr_free_buffer_pages() * (PAGE_SIZE >> 10);
min_free_kbytes = int_sqrt(lowmem_kbytes * 16);
if (min_free_kbytes < 128)
min_free_kbytes = 128;
if (min_free_kbytes > 65536)
min_free_kbytes = 65536;

用户可以通过文件/proc/sys/vm/min_free_kbytes来读取当前的值

好假设我们已经确定了全局变量 min_free_kbytpes的值,接下来我们计算三个水印。
低端内存域和高端内存域是分开计算的,从下面的步骤中可以体会
A 将min_free_kbytes 折合成页面数 pages_min。
B 计算所有低端内存域的内存页总数,保存在lowmem_pages 
for_each_zone(zone) {
if (!is_highmem(zone))
lowmem_pages += zone->present_pages;
}
C 对于每个低端内存域,根据每个内存域的页面多少,按照比例,共留出 pages_min个页面
即 
     tmp = (zone->present_pages /lowmem_pages) *pgaes_min;
    
    pages_min = tmp;
    pages_low = tmp + tmp/4;
    page_high = tmp + tmp/2;
D 对于高端内存域 首先也是计算tmp
   tmp = (zone->zone->present_pages /lowmem_pages) *pgaes_min;
   pages_min = zone->present_pages / 1024; 
   将pages_min调整到 [SWAP_CLUSTER_MAX ,128]之内。
   pages_low =  pgaes_min + tmp/4;
   pages_high = pages_min + tmp/2;
 
------------------------------------------------------------------------------------------
解决完水印的计算问题,到了  zone_water_mark_ok
free_pages = 内存域分配完 阶为order的页面数后剩余的页面
如果 free_pages <= min +zpme->lowreserve[classzone_idx] //此处我存在疑惑 
 则表示不能满足水印条件,不能分配

接下来有一部分代码不太容易理解,我把自己的理解讲述一下,当然不一定正确
代码如下:
for (o = 0; o < order; o++) {
/* At the next order, this order's pages become unavailable */
free_pages -= z->free_area[o].nr_free << o;

/* Require fewer higher order pages to be free */
min >>= 1;

if (free_pages <= min)
return 0;
}

本来,分配完后,只要剩余的页数大于水位,就可以安然返回OK,但是伙伴系统不光要考虑剩余页的总数
还要考虑0 ~order 阶 剩余页的情况, 这个循环其实是为了保证位于高阶和低阶的页大体均衡。
尤其是free_pages比较少,正好位于水印附近的时候,要保证高阶页面总数和低阶的大体均衡。
--------------------------------------------------------------------------------------
遗留的问题:

   free_pages <= min + zone->lowreserve[classzone_idx] 
   这个判断条件中的后半部zone->lowreserve[classzone_idx]  不太明白是什么用处。









阅读(4181) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chenspnjupt2011-11-19 09:00:11

free_pages <= min + zone->lowreserve[classzone_idx]
   这个判断条件中的后半部zone->lowreserve[classzone_idx]  不太明白是什么用处。
---指明在处理内存不足的临界情况下每个管理区必须保持的页框数目

chenspnjupt2011-11-19 08:32:57

谢谢楼主分享,但是下面这个好像有点问题:
在分配高端内存域时,进一步放宽限制
代码中有如下:
          if (alloc_flags & ALLOC_HIGH)
                min -= min / 2;
---------------------------------------------------------------
这个并不是指的高端内存,而是设置__GFP_ATOMIC标志,
是非常紧急的内存分配请求,如果得不到内存,对内核的稳定
性都会有很大的影响。