《LINUX3.0内核源代码分析》第四章:内存管理(4)

简介: 摘要:本文主要讲述linux如何处理ARM cortex A9多核处理器的内存管理部分。主要包括对页面释放流程的介绍。 法律声明:《LINUX3.0内核源代码分析》系列文章由谢宝友(scxby@163.com)发表于http://xiebaoyou.blog.chinaunix.net,文章中的LINUX3.0源代码遵循GPL协议。
摘要:本文主要讲述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 统计计数,对释放的页面数量进行计数 */

         free_one_page(page_zone(page), page, order,

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

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

}

 

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

 

相关文章
|
6月前
|
存储 Java Linux
【深入研究Hotspot源码与Linux内核】
【深入研究Hotspot源码与Linux内核】
|
5月前
|
网络协议 Linux 调度
谈谈如何学习Linux内核
谈谈如何学习Linux内核
|
Linux 索引
LINUX进阶(基础篇)之内存管理
LINUX进阶(基础篇)之内存管理
137 0
|
机器学习/深度学习 Linux
Linux2.6.32内核笔记(5)在应用程序中移植使用内核链表【转】
转自:http://blog.csdn.net/Deep_l_zh/article/details/48392935 版权声明:本文为博主原创文章,未经博主允许不得转载。 摘要:将内核链表移植到应用程序中,实现创建,添加节点,遍历,删除的操作。
740 0