Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1413039
  • 博文数量: 1334
  • 博客积分: 645
  • 博客等级: 上士
  • 技术积分: 5762
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-25 16:56
文章分类

全部博文(1334)

文章存档

2014年(108)

2013年(1059)

2012年(169)

分类: LINUX

2013-02-21 05:35:02

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

法律声明LINUX3.0内核源代码分析》系列文章由谢宝友()发表于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);/* 恢复中断 */

}

 

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

 

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