我们在阅读源码时,函数功能可以分为两类:1. bootmem.c 2. page_alloc.c。

  1. bootmem.c是关于bootmem allocator的,上篇文章已经简述过。

  2. page_alloc.c是关于Memory Management subsystem的。

  关于内存管理子系统的初始化调用了多个函数,我们首先分析在bootmem_init中调用的add_active_range函数。

  start_kernel --> setup_arch ---> arch_mem_init ---> bootmem_init ---> add_active_range.

  通过上述分析,我们此时可以确认内存信息,那么我们确认的内存信息必然要告诉Memory Management subsystem,首先通过add_active_range完成。

  调用两次add_active_range:

    1. add_active_range(0, start, end);     // start = 0, end = 57344

    2. add_active_range(0, start, end);     // start = 196608, end = 262144

/**
* add_active_range - Register a range of PFNs backed by physical memory 【注册物理内存的PFN范围】
* @nid: The node ID the range resides on
* @start_pfn: The start PFN of the available physical memory
* @end_pfn: The end PFN of the available physical memory
* @id :    该物理内存所属的内存结点。由于我们是UMA系统,只用一个内存结点,所以我们在调用时,传入的参数为0.
* @start_pfn: 可用物理内存的开始PFN号
* @end_pfn: 可用屋里内存的结束PFN号
* These ranges are stored in an early_node_map[] and later used by
* free_area_init_nodes() to calculate zone sizes and holes. If the
* range spans a memory hole, it is up to the architecture to ensure
* the memory is not freed by the bootmem allocator. If possible
* the range being registered will be merged with existing ranges.
* 传入的物理内存信息存储到一个数组中:early_node_map[], 稍后会在 free_area_init_nodes() 函数中使用,用来计算 zone sizes 和 holes。
* 如果物理内存的范围包含一个 memory hole,it is up to the architecture to ensure the memory is not freed by the bootmem allocator.
* 新注册的物理内存范围会Merge到已经存在的物理内存范围中去。
*/
void __init add_active_range(unsigned int nid, unsigned long start_pfn,
unsigned long end_pfn)
{
int i; mminit_dprintk(MMINIT_TRACE, "memory_register",
"Entering add_active_range(%d, %#lx, %#lx) "
"%d entries of %d used\n",
nid, start_pfn, end_pfn,
nr_nodemap_entries, MAX_ACTIVE_REGIONS); mminit_validate_memmodel_limits(&start_pfn, &end_pfn); // 对start_pfn 和 end_pfn 做某些验证,我们不Care /* Merge with existing active regions if possible */
for (i = ; i < nr_nodemap_entries; i++) {
if (early_node_map[i].nid != nid)
continue; /* Skip if an existing region covers this new one */
if (start_pfn >= early_node_map[i].start_pfn &&
end_pfn <= early_node_map[i].end_pfn)
return; /* Merge forward if suitable */
if (start_pfn <= early_node_map[i].end_pfn &&
end_pfn > early_node_map[i].end_pfn) {
early_node_map[i].end_pfn = end_pfn;
return;
} /* Merge backward if suitable */
if (start_pfn < early_node_map[i].start_pfn &&
end_pfn >= early_node_map[i].start_pfn) {
early_node_map[i].start_pfn = start_pfn;
return;
}
} /* Check that early_node_map is large enough */ // earlay_node_map数组有上限
if (i >= MAX_ACTIVE_REGIONS) {
printk(KERN_CRIT "More than %d memory regions, truncating\n",
MAX_ACTIVE_REGIONS);
return;
} early_node_map[i].nid = nid;
early_node_map[i].start_pfn = start_pfn;
early_node_map[i].end_pfn = end_pfn;
nr_nodemap_entries = i + ;
  /*
    early_node_map[0].nid = 0;
    early_node_map[0].start_pfn = 0;
    early_node_map[0].end_pfn = 57344;
    early_node_map[1].nid = 0;
    early_node_map[1].start_pfn = 196608;
    early_node_map[1].end_pfn = 262144;     很好理解,不啰嗦了!!!
  */
}

  总结:我们在从command_line中确定了屋里内存信息后,这是第一个把这个好消息告诉了buddy system。所以,一定要记住这个关键的数组——>early_node_map.

内存管理初始化源码4:add_active_range的更多相关文章

  1. 内存管理初始化源码1:setup_arch

    源码声明:基于Linux kernel 3.08 1. 在kernel/arch/mips/kernel/head.S中会做一些特定硬件相关的初始化,然后会调用内核启动函数:start_kernel: ...

  2. 内存管理初始化源码2:setup_arch

    PFN相关宏说明: /* kernel/include/linux/pfn.h */ PFN : Page Frame Number(物理页帧) /* * PFN_ALIGN:返回地址x所在那一页帧的 ...

  3. 内存管理初始化源码3:bootmem

    start_kernel ——> setup_arch ——> arch_mem_init ——> bootmem_init ——> init_bootmem_node: 此时 ...

  4. 内存管理初始化源码5:free_area_init_nodes

    start_kernel ——> setup_arch ——> arch_mem_init ——> |——> bootmem_init  |——> device_tree ...

  5. C++动态内存管理与源码剖析

    引言 在本篇文章中,我们主要剖析c++中的动态内存管理,包括malloc.new expression.operator new.array new和allocator内存分配方法以及对应的内存释放方 ...

  6. Jedis cluster集群初始化源码剖析

    Jedis cluster集群初始化源码剖析 环境 jar版本: spring-data-redis-1.8.4-RELEASE.jar.jedis-2.9.0.jar 测试环境: Redis 3.2 ...

  7. C#共享内存实例 附源码

    原文 C#共享内存实例 附源码 网上有C#共享内存类,不过功能太简单了,并且写内存每次都从开头写.故对此进行了改进,并做了个小例子,供需要的人参考. 主要改进点: 通过利用共享内存的一部分空间(以下称 ...

  8. Firefly卡牌手游《暗黑世界V1.5》服务器端源码+GM管理后台源码

    http://www.9miao.com/content-6-304.html Firefly卡牌手游<暗黑世界V1.5>服务器端源码+GM管理后台源码 关于<暗黑世界V1.5> ...

  9. 内存管理 初始化(八) 至kswapd_init

    至此,内存初始化部分已看完,遗留问题: 1.对于unicore或者mips的页表建立都很清楚,但是对于ARM我不清楚: 初始化部分涉及的页表映射建立,我都以unicore架构为准,ARM的页表映射从原 ...

随机推荐

  1. dota2输入法无候选框?

    win10自带的微软拼音在dota2中不会显示候选框,或者说是选词框. 这种情况下只能选择其他输入法. 我选择的是搜狗输入法(此随笔添加时的最新版),在dota2中有选词框. 网上有些人说要改兼容性, ...

  2. jqgrid 自定义文本框、选择框等查询

    要实现jqgrid的自定义查询可通过表格获取查询的条件,再给jqgrid表格发送postData参数. HTML: <table id="querytable" border ...

  3. Vue管理系统前端系列一vue-cli4.x 初始化项目

    目录 项目介绍 技术基础 开发环境 安装工具 快速原型开发 创建项目 配置相关说明 目录结构 项目介绍 lion-ui 是一个基于 RBAC 的管理系统前端项目,采用 vue 和 element-ui ...

  4. 原生js实现 vue的数据双向绑定

    原生js实现一个简单的vue的数据双向绑定 vue是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时 ...

  5. Cinder Volume 服务启动流程分析和周期性任务分析

    1.cinder-volume服务的程序入口 #!/usr/bin/python2 # PBR Generated from u'console_scripts' import sys from ci ...

  6. AltiumDesigner画图不求人11 | 提高AD20启动速度的方法七选择手动释放工程 | 视频教程 | 你问我答

    往期文章目录 AD画图不求人1 | AD20软件安装视频教程 | 含软件安装包 AD画图不求人2 | 中英文版本切换 AD画图不求人3 | 高亮模式设置 AD画图不求人4 | 双击设计文件无法启动Al ...

  7. Mysql锁【转】

    一.概述 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则.对于任何一种数据库来说都需要有相应的锁定机制,所以MySQL自然也不能例外. M ...

  8. 必看!2020最新黑马JAVA 学习路线

    https://www.fang1688.cn/2020/08/24/%e5%bf%85%e7%9c%8b%ef%bc%81java-%e5%ad%a6%e4%b9%a0%e8%b7%af%e7%ba ...

  9. 【Pod Terminating原因追踪系列之二】exec连接未关闭导致的事件阻塞

    前一阵有客户docker18.06.3集群中出现Pod卡在terminating状态的问题,经过排查发现是containerd和dockerd之间事件流阻塞,导致后续事件得不到处理造成的. 定位问题的 ...

  10. e3mall商城的归纳总结7之solr搭建和应用

    敬给读者的话 本文主要应用的技术是solr技术的搭建和应用,本文小编尽量写的更详细一些,让读者在不考虑项目的情况下也能正常完成solr的搭建,说完搭建之后,再说明运行solrj在项目中如何应用solr ...