原本由bootmem管理的内存在mem_init函数中交由伙伴系统管理。

1.free_unused_memmap_node

相邻的membank间可能存在空洞,但在bootmem阶段这些空洞页也分配了page结构体。该函数的作用是找到这些page结构体所占用的内存并且释放掉。

static void __init free_unused_memmap_node(int node, struct meminfo *mi)
-->unsigned long bank_start; //前一个membank的结束地址
-->unsigned long prev_bank_end ;//后一个membank的起始地址
-->free_memmap(node, prev_bank_end, bank_start);
-->struct page *start_pg = pfn_to_page(prev_bank_end);
-->struct page *end_pg = pfn_to_page(bank_start);
-->unsigned long pg = PAGE_ALIGN(__pa(start_pg));
-->unsigned long pgend = __pa(end_pg) & PAGE_MASK;
-->free_bootmem_node(NODE_DATA(node), pg, pgend - pg);

2.移交bootmem分配剩余的空闲页到伙伴系统

该函数返回的是返回给伙伴系统的空闲页数。

unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
{
register_page_bootmem_info_node(pgdat);
return free_all_bootmem_core(pgdat->bdata);
}

空闲页保存在全局变量totalram_pages中

/*mm/page_alloc.c*/
unsigned long totalram_pages __read_mostly;

totalram_pages += free_all_bootmem_node(pgdat);

2.1该函数的核心是free_all_bootmem_core(pgdat->bdata)

static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
-->__free_pages_bootmem(pfn_to_page(start), order);
-->释放掉bdata->node_bootmem_map所占用的内存,彻底废弃bootmem分配器

释放页到伙伴系统底层调用的两个函数是

void __free_pages(struct page *page, unsigned int order)
#define __free_page(page) __free_pages((page), 0)

可以看到,最终调用的还是__free_pages函数

void __free_pages(struct page *page, unsigned int order)
{
if (put_page_testzero(page)) {
if (order == )
free_hot_page(page);
else
__free_pages_ok(page, order);
}
}

free_hot_page流程如下

free_hot_page(page);
-->free_hot_cold_page(page, );
-->struct zone *zone = page_zone(page);
-->struct per_cpu_pages *pcp = &zone_pcp(zone, get_cpu())->pcp;
-->if (cold)
list_add_tail(&page->lru, &pcp->list);/*冷页插入队列末尾*/
else
list_add(&page->lru, &pcp->list);/*热页插入队列首*/
-->pcp->count++;
-->if (pcp->count >= pcp->high)
-->free_pages_bulk(zone, pcp->batch, &pcp->list, );
-->从队列末尾开始删除pcp->batch个页
-->__free_one_page(page, zone, order);/*把删除的页释放到伙伴系统*/

__free_pages_ok流程如下:

static void __free_pages_ok(struct page *page, unsigned int order)
-->free_one_page(page_zone(page), page, order);
-->__free_one_page(page, zone, order);

可以看出,最终调用相同的底层函数__free_one_page,这个函数的实现可以说是伙伴系统的精髓。

这里注意空闲页加入伙伴系统后要做如下的设置。

set_page_order(page, order);
-->set_page_private(page, order);/*设置page->private*/
-->__SetPageBuddy(page);/*设置page->flags*/
list_add(&page->lru,&zone->free_area[order].free_list[migratetype]);
zone->free_area[order].nr_free++;

mem_init()的更多相关文章

  1. 内存管理 初始化(四)mem_init bootmem 迁移至伙伴系统

    mm_init中执行mem_init,将原通过bootmem分配器管理的低端内存 及  通过meminfo得知的高端内存释放到伙伴系统中,最后bootmem位图本身占用的低端内存物理页也被释放进伙伴系 ...

  2. MMU工作原理

    MMU的工作原理就是把虚拟地址转换成物理地址. 虚拟地址:由编译器和连接器在定位程序时分配. 物理地址:用来访问实际的主存硬件模块. 使用虚拟存储器的系统都使用一种称为分页(paging).虚拟地址空 ...

  3. MIT 6.828 JOS学习笔记17. Lab 3.1 Part A User Environments

    Introduction 在这个实验中,我们将实现操作系统的一些基本功能,来实现用户环境下的进程的正常运行.你将会加强JOS内核的功能,为它增添一些重要的数据结构,用来记录用户进程环境的一些信息:创建 ...

  4. MIT 6.828 JOS学习笔记16. Lab 2.2

    Part 3 Kernel Address Space JOS把32位线性地址虚拟空间划分成两个部分.其中用户环境(进程运行环境)通常占据低地址的那部分,叫用户地址空间.而操作系统内核总是占据高地址的 ...

  5. MIT 6.828 JOS学习笔记15. Lab 2.1

    Lab 2: Memory Management lab2中多出来的几个文件: inc/memlayout.h kern/pmap.c kern/pmap.h kern/kclock.h kern/k ...

  6. Linux内存管理之bootmem分配器

    为什么要使用bootmem分配器,内存管理不是有buddy系统和slab分配器吗?由于在系统初始化的时候需要执行一些内存管理,内存分配的任务,这个时候buddy系统,slab分配器等并没有被初始化好, ...

  7. Linux0.11内核--内存管理之1.初始化

    [版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5597705.html ] Linux内核因为使用了内存分页机制,所以相对来说好理解些.因为内存 ...

  8. (三)内存 SDRAM 驱动实验 (杨铸 130 页)(勉强能懂个大概)

    SDRAM 芯片讲解: 地址: 行地址 (A0-A12) 列地址 (A0-A8)    片选信号(BA0 BA1)(L-BANK)(因为SDRAM有 4片) 两片SDRAM 连线唯一区别在 UDQM ...

  9. Linux启动过程详述

    http://www.ibm.com/developerworks/cn/linux/kernel/startup/index.html Linux启动第1步:引导内核 Linux启动第2步:内核部分 ...

随机推荐

  1. IIS下FTP服务器的PASV端口范围修改方法

    应该有不少使用IIS自带的FTP服务器,IIS的FTP里的PASV模式下默认端口范围1024 - 65535,连接时会从中随机选择到响应.这样的超大范围就给服务器安全带来的隐患. 虽然可以通过一些方法 ...

  2. DNS安全浅议、域名A记录(ANAME),MX记录,CNAME记录 专题

    首先要做的就是配置域名的MX 记录啦: 先添加一条A记录: mail.abc.com 指向 你的服务器IP! 然后添加域名的MX 记录,指向mail.abc.com A 记录( 即域名MX 记录的值为 ...

  3. Unity C# 脚本的单例

    今天学习了一个比较不错的单例模式 public class UnitySigleton <T>: MonoBehaviour where T:class { public static T ...

  4. magento新增商品属性以及将属性加入Flat table

    magento的EAV模型非常强大且灵活,但是如果不做优化的话,性能会非常低,因为attributes都存放在附表里,要获取一个entity的attribute,需要表联结一次,如果需要获取多条att ...

  5. vue-resource的使用

    之前使用axios post请求不能向后台发送数据,然后使用了vue-resource这个插件 import  Vue from 'vue' import VueResource from 'vue- ...

  6. 微信小程序:点击预览图片

    在开发微信小程序时,开发人员会参考着小程序api来开发小程序,但有的时候根据情况不同很容易出现bug,以下是我在开发小程序时出现的各种bug,在开发时有需要预览图片. 1.xml <view c ...

  7. Android在应用设置里关闭权限,返回生命周期处理

    问题 在处理6.0运行时权限时,很多人都忽略了这样一个问题: 在一个App应用里,如果已经允许了一个权限比如(读取通讯权限),此刻去调用相机,弹出权限申请对话框,此刻点击拒绝,然后经过处理后弹出去设置 ...

  8. pat甲级1016

    1016 Phone Bills (25)(25 分) A long-distance telephone company charges its customers by the following ...

  9. java Vamei快速教程12 类型转换和多态

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们之前使用类创造新的类型(type),并使用继承来便利我们创建类的过程.我将在这 ...

  10. 「C基础」C运算符的优先级

    一.运算符的优先级表 C 语言的符号众多,由这些符号又组合成了各种各样的运算符.既然是运算符就一定有其特定的优先级,下表就是C 语言运算符的优先级表: 注:同一优先级的运算符,运算次序由结合方向所决定 ...