Chinaunix首页 | 论坛 | 博客
  • 博客访问: 231545
  • 博文数量: 37
  • 博客积分: 933
  • 博客等级: 军士长
  • 技术积分: 511
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-16 10:15
文章分类
文章存档

2012年(1)

2011年(36)

分类: LINUX

2011-03-17 10:07:04

在介绍__alloc_pages前不得不提一下:
    UNIX操作系统简单而一致,但只有天才才能领会并欣赏其简单性。
                      ----Dennis Ritchie
                                             我们疯了,你也一样;
__alloc_pages被称为伙伴系统的心脏,同时他也是linux最为冗长的几个函数
之一。
在正式读这个函数之前,我们把相应的辅助函数说明一下:
 888 static struct page *
 889 get_page_from_freelist(gfp_t gfp_mask, unsigned int order,
 890                 struct zonelist *zonelist, int alloc_flags)
 891 {
 892         struct zone **z = zonelist->zones;
 893         struct page *page = NULL;
 894         int classzone_idx = zone_idx(*z);
 895
 896         /*
 897          * Go through the zonelist once, looking for a zone with enough free.
 898          * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
 899          */
 900         do {
 901                 if ((alloc_flags & ALLOC_CPUSET) &&
 902                                 !cpuset_zone_allowed(*z, gfp_mask))
 903                         continue;
 904
 905                 if (!(alloc_flags & ALLOC_NO_WATERMARKS)) {
 906                         unsigned long mark;
 907                         if (alloc_flags & ALLOC_WMARK_MIN)
 908                                 mark = (*z)->pages_min;
 909                         else if (alloc_flags & ALLOC_WMARK_LOW)
 910                                 mark = (*z)->pages_low;
 911                         else
 912                                 mark = (*z)->pages_high;
 913                         if (!zone_watermark_ok(*z, order, mark,
 914                                     classzone_idx, alloc_flags))
 915                                 if (!zone_reclaim_mode ||
 916                                     !zone_reclaim(*z, gfp_mask, order))
 917                                         continue;
 918                 }
 919
 920                 page = buffered_rmqueue(zonelist, *z, order, gfp_mask);
 921                 if (page)
 922                         break;
 923         } while (*(++z) != NULL);
 924         return page;
 925 }
这个函数在__alloc_pages中被反复调用:他遍历各个管理区(ZONE_DMA,ZONE_DMA32,ZONE_NORMAL,ZONE_HIGHMEM),
并根据相应的mark(水位线值)进行空闲页框的分配工作(实际上是调用buffered_rmqueue进行分配。)这个函数中还调用了一个
比较重要的函数zone_watermark_ok,这个函数检查伙伴系统中有否有满足要求的连续空闲页数可以分配。在此,不得不说明一下
水位线(watermark)的概念。

在这值规定了系统中的内存量必须维持在这个水位之上:好比水杯里的水,你喝过一口之后,剩下的不能小于某个刻度线(水位线)。
那么,这个水位线由谁规定的呢?OK,zone_watermark_ok does it!
857 int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
     /*  */
 858                       int classzone_idx, int alloc_flags)
 859 {
 860         /* 该区中现在空闲的页面总数减去要分配出去的页面,free_pages变成负数也没有关系 */
 861         long min = mark, free_pages = z->free_pages - (1 << order) + 1;
 862         int o;
 863   //如果设置了ALLOC_HIGH标志,水位线变成原来的一半,你能喝的水变多。
 864         if (alloc_flags & ALLOC_HIGH)
 865                 min -= min / 2;
     //如果设置了ALLOC_HARDER,进一步的降低水位线
 866         if (alloc_flags & ALLOC_HARDER)
 867                 min -= min / 4;
 868
     //如果分配过后剩余的页面数小于水位线,也就是说你这次要拿走的内存多于我想过你的内存
     //返回0
 869         if (free_pages <= min + z->lowmem_reserve[classzone_idx])
 870                 return 0;
     //到这里说明了,分配后剩下的页面数是大于水位线值的
     //但是,有一点需要考虑:是否这些可用的内存是出自于低阶的
     //链表中,例如:所请求的order=5 分配连续内存页框数为32
     //此时,系统的free_pages有可能全部来源于order=0,1,2,3,4阶的
     //页面,这个情况要排除出去
 871         for (o = 0; o < order; o++) {
 872                 /* At the next order, this order's pages become unavailable */
 873                 free_pages -= z->free_area[o].nr_free << o;
 874
 875                 /* Require fewer higher order pages to be free */
 876                 min >>= 1;
 877
 878                 if (free_pages <= min)
 879                         return 0;
 880         }
 881         return 1;
每个zone中的描述符中都有三个字段:
pages_low:
pages_min;
pages_high;
这三个字段规定了该区中剩余的空闲内存量应该维持在什么水平。
(待续)
阅读(3147) | 评论(1) | 转发(0) |
0

上一篇:伙伴系统

下一篇:slab分析(一)

给主人留下些什么吧!~~

2011-09-04 11:35:32

楼主,请教你几个问题哈。
zone_watermark_ok,应该是判断在分配了内存之后,剩余的页是否大于系统给定的水印。
1. free_pages = z->free_pages - (1 << order) + 1; // 这里为什么还要加1呢?
2. min >>= 1; // 这句话,具体作用是什么呢?