Chinaunix首页 | 论坛 | 博客
  • 博客访问: 804346
  • 博文数量: 59
  • 博客积分: 958
  • 博客等级: 准尉
  • 技术积分: 2459
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-21 13:36
文章分类
文章存档

2019年(1)

2018年(5)

2017年(7)

2015年(2)

2014年(4)

2012年(10)

2011年(30)

分类: LINUX

2011-12-04 19:35:51

摘要:本文主要讲述linux如何处理ARM cortex A9多核处理器的内存管理部分。主要包括对页面释放流程的介绍。

法律声明LINUX3.0内核源代码分析》系列文章由谢宝友(scxby@163.com)发表于http://xiebaoyou.blog.chinaunix.net,文章中的LINUX3.0源代码遵循GPL协议。除此以外,文档中的其他内容由作者保留所有版权。谢绝转载。

1.1.1      释放页面

释放页面的主函数是__free_pages

/**

 * 释放内存页

 *              page:        要释放的内存页

 *              order:       与释放的页数量为2^order

 */

void __free_pages(struct page *page, unsigned int order)

{

         if (put_page_testzero(page)) {/* 一般来说,应当在页面引用计数变为0时才会调用释放函数,这里进行引用计数判断是安全起见 */

                   if (order == 0)/* 如果是释放单个页面,则释放到管理区的每CPU页面缓存中,以加快单页分配速度 */

                            free_hot_cold_page(page, 0);

                   else

                            __free_pages_ok(page, order);/* 否则直接释放到伙伴系统中 */

         }

}

 

/**

 * 释放单个页面到伙伴系统(页面缓存)中。

 *              page:        要释放的页面

 *              cold:          要释放的页面是热页还是冷页。决定是页面放入热池还是冷池。

 */

void free_hot_cold_page(struct page *page, int cold)

{

         /* 找到页面所属的管理区 */

         struct zone *zone = page_zone(page);

         struct per_cpu_pages *pcp;

         unsigned long flags;

         int migratetype;

         int wasMlocked = __TestClearPageMlocked(page);/* 页面是否被锁住 */

 

         /**

          * free_pages_prepare主要是检查页面状态是否允许释放,避免错误的释放页面。

          * 并且处理一些调试相关的事务。

          */

         if (!free_pages_prepare(page, 0))

                   return;

 

         migratetype = get_pageblock_migratetype(page);

         set_page_private(page, migratetype);

         local_irq_save(flags);

         if (unlikely(wasMlocked))/* 如果页面是由mlock锁住的页,这里调用free_page_mlock进行统计计数 */

                   free_page_mlock(page);

         __count_vm_event(PGFREE);/* 统计本CPU上的页面释放次数 */

 

         /*

          * We only track unmovable, reclaimable and movable on pcp lists.

          * Free ISOLATE pages back to the allocator because they are being

          * offlined but treat RESERVE as movable pages so we can get those

          * areas back if necessary. Otherwise, we may have to free

          * excessively into the page allocator

          */

         if (migratetype >= MIGRATE_PCPTYPES) {/* 该页面目前不受每CPUPCP链表管理 */

                   if (unlikely(migratetype == MIGRATE_ISOLATE)) {/* 该页面是从邻近的CPU管理区中调配过来的,仍然放到MIGRATE_ISOLATE中,不转化为可迁移的页面 */

                            free_one_page(zone, page, 0, migratetype);

                            goto out;

                   }

                   /* 如果是从保留的链表中分配的页面,也将其放入可移动页中 */

                   migratetype = MIGRATE_MOVABLE;

         }

 

         /* 取得本CPU的页面缓存对象 */

         pcp = &this_cpu_ptr(zone->pageset)->pcp;

         if (cold)/* 如果是冷页,则CPU缓存中还没有页面数据,将页面放入页面缓存链表的尾部。 */

                   list_add_tail(&page->lru, &pcp->lists[migratetype]);

         else

                   list_add(&page->lru, &pcp->lists[migratetype]);/* 否则放入列表的首部,这样后续的分配过程可以利用CPU缓存中的热缓存 */

         pcp->count++;/* 当前CPU页面缓存计数 */

         if (pcp->count >= pcp->high) {/* 页面缓存中保留的页面太多,超过上限了 */

                   free_pcppages_bulk(zone, pcp->batch, pcp);/* 将页面缓存中的页面释放一部分到伙伴系统中 */

                   pcp->count -= pcp->batch;/* 递减PCP中的缓存页面数量 */

         }

 

out:

         local_irq_restore(flags);/* 恢复中断 */

}

 

/**

 * 直接释放页面到伙伴系统中

 */

static void __free_pages_ok(struct page *page, unsigned int order)

{

         unsigned long flags;

         int wasMlocked = __TestClearPageMlocked(page);

 

         if (!free_pages_prepare(page, order))/* 如果释放页面失败(如重要的管理结构被破坏,或者错误的调用参数)则退出 */

                   return;

 

         local_irq_save(flags);/* 接下来要操作伙伴系统了,由于在中断里面也会操作伙伴系统,因此这里需要关中断 */

         if (unlikely(wasMlocked))/* 如果页面是被mlock系统调用锁住的,就进行一些统计计数 */

                   free_page_mlock(page);

         __count_vm_events(PGFREE, 1 << order);/* 统计计数,对释放的页面数量进行计数 */

         free_one_page(page_zone(page), page, order,

                                               get_pageblock_migratetype(page));/* 将页面释放到伙伴系统中 */

         local_irq_restore(flags);/* 恢复中断 */

}

 

可以看到,释放页面的流程比较简单,基本上就是伙伴系统函数的简单封装。接下来我们开始介绍伙伴系统。

 

阅读(4876) | 评论(4) | 转发(10) |
给主人留下些什么吧!~~

xiebaoyou2011-12-11 13:41:21

鸟菜小: pages的migration不需要pages offline, 为啥《Professional Linux Kernel Architecture 》中也说"move physical pages across NUMA nodes"? 我只在m.....
最初我也是根据PLK来解释MIGRATE_ISOLATE的含义,认为它表示页面在不同的NUMA节点之间移动产生的。但是从代码上看,它的含义应当是指在进行内存热插拨时,暂时性将页面移动到MIGRATE_ISOLATE列表,防止这个列表的页面被再次分配出去。这与isolate的意思是一致的,并且与代码注释也是一致的:
#define MIGRATE_ISOLATE       4 /* can't allocate from here */
也许是PLK作者搞错。

鸟菜小2011-12-10 15:57:36

pages的migration不需要pages offline, 为啥《Professional Linux Kernel Architecture 》中也说"move physical pages across NUMA nodes"? 我只在memory hotplug的调用路径中看到了对pages的MIGRATE_ISOLATE设置。老谢能否指点下?

鸟菜小2011-12-10 15:38:39

MIGRATE_ISOLATE的意思不是说页面是从邻近的CPU中调来的吧?而是说页面以后不能再分配出去了,例如pages正在被offlined(目前貌似就只有这一种情况)。

湿了耶2011-12-06 23:20:48


我在看,眼都花了