免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3339 | 回复: 0

[内存管理] 有关get_page_from_freelist的一些问题 [复制链接]

论坛徽章:
0
发表于 2012-09-03 21:29 |显示全部楼层
本帖最后由 hshopeful 于 2012-09-04 10:13 编辑
  1. static struct page *
  2. get_page_from_freelist(gfp_t gfp_mask, unsigned int order,
  3.                 struct zonelist *zonelist, int alloc_flags)
  4. {
  5.         struct zone **z;//管理区结构体
  6.         struct page *page = NULL;
  7.         int classzone_idx = zone_idx(zonelist->zones[0]);//#define zone_idx(zone)        ((zone) - (zone)->zone_pgdat->node_zones) 获取管理区的编号
  8.         struct zone *zone;
  9.         nodemask_t *allowednodes = NULL;/* zonelist_cache approximation */
  10.         int zlc_active = 0;                /* set if using zonelist_cache */
  11.         int did_zlc_setup = 0;                /* just call zlc_setup() one time */
  12.         enum zone_type highest_zoneidx = -1; /* Gets set for policy zonelists */

  13. zonelist_scan:
  14.         /*
  15.          * Scan zonelist, looking for a zone with enough free.
  16.          * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
  17.          */
  18.         z = zonelist->zones;//让z指向第一个管理区
  19.         // 在允许的节点中,遍历满足要求的管理区
  20.         do {
  21.                 /*
  22.                  * In NUMA, this could be a policy zonelist which contains
  23.                  * zones that may not be allowed by the current gfp_mask.
  24.                  * Check the zone is allowed by the current flags
  25.                  */
  26.                 if (unlikely(alloc_should_filter_zonelist(zonelist))) {//根据zonelist->zlcache_ptr来确定是否需要过滤掉此内存区链表,关于过滤的条件还不是很清楚,请指教
  27.                         if (highest_zoneidx == -1)
  28.                                 highest_zoneidx = gfp_zone(gfp_mask);//gfp_zone用于指定分配内存的内存域
  29.                         if (zone_idx(*z) > highest_zoneidx)//首先考虑利用上面指定的内存域,对于一些分配代价高于指定内存域的内存域先不考虑
  30.                                 continue;
  31.                 }

  32.                 if (NUMA_BUILD && zlc_active &&//是第一遍分配,在其他管理区中分配页面时需要考虑其页面是否充足
  33.                         !zlc_zone_worth_trying(zonelist, z, allowednodes))//该管理区页面不是很充足,考虑下一个管理区
  34.                                 continue;
  35.                 zone = *z;
  36.                 if ((alloc_flags & ALLOC_CPUSET) &&
  37.                         !cpuset_zone_allowed_softwall(zone, gfp_mask))//当前分配标志不允许在该管理区中分配页面
  38.                                 goto try_next_zone;

  39.                 if (!(alloc_flags & ALLOC_NO_WATERMARKS)) {//分配时需要考虑watermark
  40.                         unsigned long mark;//根据分配标志,确定使用哪一个watermark
  41.                         if (alloc_flags & ALLOC_WMARK_MIN)
  42.                                 mark = zone->pages_min;
  43.                         else if (alloc_flags & ALLOC_WMARK_LOW)
  44.                                 mark = zone->pages_low;
  45.                         else
  46.                                 mark = zone->pages_high;
  47.                         if (!zone_watermark_ok(zone, order, mark,
  48.                                     classzone_idx, alloc_flags)) {//该管理区的可用内存不可以满足本次分配的要求
  49.                                 if (!zone_reclaim_mode ||//但不满足分配要求时,如果此内存域不能回收内存或者是回收不到可用内存时,就会跳转到this_zone_full
  50.                                     !zone_reclaim(zone, gfp_mask, order))
  51.                                         goto this_zone_full;
  52.                         }
  53.                 }

  54.                 page = buffered_rmqueue(zonelist, zone, order, gfp_mask);//调用伙伴系统的分配函数
  55.                 if (page)// 从伙伴系统分配成功,退出
  56.                         break;
  57. this_zone_full:
  58.                 if (NUMA_BUILD)
  59.                         zlc_mark_zone_full(zonelist, z);//标记该管理区空间不足,下次分配时将略过本管理区,避免浪费太多时间
  60. try_next_zone:
  61.                 if (NUMA_BUILD && !did_zlc_setup) {//当前管理区内存不足,需要加大在其他区中的分配力度
  62.                         /* we do zlc_setup after the first zone is tried */
  63.                         allowednodes = zlc_setup(zonelist, alloc_flags);
  64.                         zlc_active = 1;
  65.                         did_zlc_setup = 1;
  66.                 }
  67.         } while (*(++z) != NULL);

  68.         if (unlikely(NUMA_BUILD && page == NULL && zlc_active)) {// 第一遍分配不成功,则取消zlc_active,这样会尽量从其他节点中分配内存
  69.                 /* Disable zlc cache for second zonelist scan */
  70.                 zlc_active = 0;
  71.                 goto zonelist_scan;
  72.         }
  73.         return page;
  74. }
复制代码
关于上面一段代码中zlc_active的作用不明白,还望理解的人指点一下。不甚感激!
  1. struct zonelist {
  2.         struct zonelist_cache *zlcache_ptr;                     // NULL or &zlcache
  3.         struct zone *zones[MAX_ZONES_PER_ZONELIST + 1];      // NULL delimited
  4. #ifdef CONFIG_NUMA
  5.         struct zonelist_cache zlcache;                             // optional ...
  6. #endif
  7. };
复制代码
  1. struct zonelist_cache {
  2.         unsigned short z_to_n[MAX_ZONES_PER_ZONELIST];                /* zone->nid */
  3.         DECLARE_BITMAP(fullzones, MAX_ZONES_PER_ZONELIST);        /* zone full? */
  4.         unsigned long last_full_zap;                /* when last zap'd (jiffies) */
  5. };
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP