【原创】(四)Linux内存模型之Sparse Memory Model
背景
Read the fucking source code!
--By 鲁迅A picture is worth a thousand words.
--By 高尔基
说明:
- Kernel版本:4.14
- ARM64处理器,Contex-A53,双核
- 使用工具:Source Insight 3.5, Visio
1. 介绍
顺着之前的分析,我们来到了bootmem_init()
函数了,本以为一篇文章能搞定,大概扫了一遍代码之后,我默默的把它拆成了两部分。
bootmem_init()
函数代码如下:
void __init bootmem_init(void)
{
unsigned long min, max;
min = PFN_UP(memblock_start_of_DRAM());
max = PFN_DOWN(memblock_end_of_DRAM());
early_memtest(min << PAGE_SHIFT, max << PAGE_SHIFT);
max_pfn = max_low_pfn = max;
arm64_numa_init();
/*
* Sparsemem tries to allocate bootmem in memory_present(), so must be
* done after the fixed reservations.
*/
arm64_memory_present();
sparse_init();
zone_sizes_init(min, max);
memblock_dump_all();
}
这一部分,我们将研究一下Sparse Memory Model
。
在讲Linux内存模型之前,需要补充两个知识点:PFN
和NUMA
。
1.1 physical frame number(PFN)
前面我们讲述过了虚拟地址到物理地址的映射过程,而系统中对内存的管理是以页为单位的:
page
:线性地址被分成以固定长度为单位的组,称为页,比如典型的4K大小,页内部连续的线性地址被映射到连续的物理地址中;
page frame
:内存被分成固定长度的存储区域,称为页框,也叫物理页。每一个页框会包含一个页,页框的长度和一个页的长度是一致的,在内核中使用struct page
来关联物理页。
如下图,PFN从图片中就能看出来了:
至于__page_to_pfn
这个实现取决于具体的物理内存模型,下文将进行介绍。
1.2 NUMA
UMA: Uniform Memory Access
,所有处理器对内存的访问都是一致的:
从上图中可以看出,当处理器和Core变多的时候,内存带宽将成为瓶颈问题。
NUMA: Non Uniform Memory Access
,非一致性内存访问:
从图中可以看出,每个CPU访问local memory,速度更快,延迟更小。当然,整体的内存构成一个内存池,CPU也能访问remote memory,相对来说速度更慢,延迟更大。目前对NUMA
的了解仅限于此,在内核中会遇到相关的代码,大概知道属于什么范畴就可以了。
2. Linux内存模型
Linux提供了三种内存模型(include/asm-generic/memory_model.h
):
一般处理器架构支持一种或者多种内存模型,这个在编译阶段就已经确定,比如目前在ARM64中,使用的Sparse Memory Model
。
Flat Memory
物理内存地址连续,这个也是Linux最初使用的内存模型。当内存有空洞的时候也是可以使用这个模型,只是struct page *mem_map
数组的大小跟物理地址正相关,内存有空洞会造成浪费。Discontiguous Memory
物理内存存在空洞,随着Sparse Memory
的提出,这种内存模型也逐渐被弃用了。Sparse Memory
物理内存存在空洞,并且支持内存热插拔,以section
为单位进行管理,这也是下文将分析的。
Linux三种内存模型下,struct page
到物理page frame
的映射方式也不一样,具体可以查看include/asm-generic/memory_model.h
文件中的__pfn_to_page/__page_to_pfn
定义。
关于内存模型,可以参考Memory: the flat, the discontiguous, and the sparse
3. Sparse Memory
本节分析的是ARM64, UMA(linux4.14中不支持ARM NUMA)
下的Sparse Memory
模型。
3.1 mem_section
在Sparse Memory
模型中,section
是管理内存online/offline
的最小内存单元,在ARM64中,section
的大小为1G,而在Linux内核中,通过一个全局的二维数组struct mem_section **mem_section
来维护映射关系。
函数的调用过程如下所示,主要在arm64_memory_present
中来完成初始化及映射关系的建立:
函数调用结束之后的映射关系如下图所示:
已知一个pfn
时,可以通过__pfn_to_section(pfn)
来最终找到对应的struct page
结构。
3.2 sparse_init
看看sparse_init
函数的调用关系图:
在该函数中,首先分配了usermap,这个usermap与内存的回收机制相关,用4bit的bitmap来描述page block(一个pageblock大小通常为2的次幂,比如MAX_ORDER-1)
的迁移类型:
/* Bit indices that affect a whole block of pages */
enum pageblock_bits {
PB_migrate,
PB_migrate_end = PB_migrate + 3 - 1,
/* 3 bits required for migrate types */
PB_migrate_skip,/* If set the block is skipped by compaction */
/*
* Assume the bits will always align on a word. If this assumption
* changes then get/set pageblock needs updating.
*/
NR_PAGEBLOCK_BITS
};
sparse memory
模型会为每一个section都分配一个usermap
,最终的物理页面的压缩,迁移等操作,都跟这些位相关,如下图所示:
sparse_init
函数中,另一部分的作用是遍历所有present section
,然后将其映射到vmemmap区域空间。vmemmap
区域空间,在之前的文章中也提到过。执行完后,整体的效果如下图所示:
关于Sparse Memory Model
就先分析这么多,只有结合使用sparse memory
的具体模块时,理解才会更顺畅。
一不小心就容易扣细节,而一旦陷入细节,内核就容易变成魔鬼,太难了。
【原创】(四)Linux内存模型之Sparse Memory Model的更多相关文章
- JAVA内存模型(Java Memory Model ,JMM)
http://blog.csdn.net/hxpjava1/article/details/55189077 JVM有主内存(Main Memory)和工作内存(Working Memory),主内存 ...
- 并发研究之Java内存模型(Java Memory Model)
Java内存模型JMM java内存模型定义 上一遍文章我们讲到了CPU缓存一致性以及内存屏障问题.那么Java作为一个跨平台的语言,它的实现要面对不同的底层硬件系统,设计一个中间层模型来屏蔽底层的硬 ...
- 浅析java内存模型--JMM(Java Memory Model)
在并发编程中,多个线程之间采取什么机制进行通信(信息交换),什么机制进行数据的同步? 在Java语言中,采用的是共享内存模型来实现多线程之间的信息交换和数据同步的. 线程之间通过共享程序公共的状态,通 ...
- 并发编程之java内存模型(Java Memory Model ,JMM)
一.图例 0.两个概念 Heap(堆):运行时的数据区,由垃圾回收负责,运行时分配内存(所以慢),对象存放在堆上 如果两个线程,同时调用同一个变量,怎两个线程都拥有,该对象的私有拷贝 (可以看一下,T ...
- java内存模型(Java Memory Model)
内容导航: Java内存模型 硬件存储体系结构 Java内存模型和硬件存储体系之间的桥梁: 共享对象的可见性 竞争条件 Java内存模型规定了JVM怎样与计算机存储系统(RAM)协调工作.JVM是一个 ...
- Java 内存模型(Java Memory Model,JMM)
基本概念 JMM 本身是一种抽象的概念并不是真实存在,它描述的是一组规范,通过这组规范定义了程序的访问方式 JMM 同步规定 线程解锁前,必须把共享变量的值刷新回主内存 线程加锁前,必须读取主内存的最 ...
- 探索 Linux 内存模型--转
引用:http://www.ibm.com/developerworks/cn/linux/l-memmod/index.html 理解 Linux 使用的内存模型是从更大程度上掌握 Linux 设计 ...
- 【ARM-Linux开发】Linux内存管理:ARM Memory Layout以及mmu配置
原文:Linux内存管理:ARM Memory Layout以及mmu配置 在内核进行page初始化以及mmu配置之前,首先需要知道整个memory map. 1. ARM Memory Layout ...
- Linux内存模型
http://blog.csdn.net/sunyubo458/article/details/6090946 了解linux的内存模型,或许不能让你大幅度提高编程能力,但是作为一个基本知识点应该熟悉 ...
随机推荐
- [原创实践]IBM thinkpad T61制作和使用recovery光盘进行出厂系统恢复
制作系统恢复盘 之前制作了系统恢复光盘,包含Product recovery 光盘1和光盘2,rescure and recovery光盘. 联想笔记本XP系统有一个硬盘分区是用来做恢复的,双击硬盘即 ...
- Docker 前沿概述
目录 Docker 前沿概述 什么是Docker? Docker的基本概念 容器(Container) -- 镜像运行时的实体 镜像(Image) -- 一个特殊的文件系统 仓库(Repository ...
- 测试自动化:java+selenium3 UI自动化(1) - 环境搭建
1.前言 我大概是在2012年第一次正式接触到自动化测试,那个时候跟随我的团队一起,就当时项目的UI自动化尝试做出了探索. 在我离开那家公司的时候,我们的自动化测试体系仍然难言完美,但是也已经达到了非 ...
- Eureka 缓存结构以及服务感知优化
目录 Eureka-Client获取注册信息 Eureka-Server管理注册信息 服务感知优化 果然好记性不如烂笔头,再简单的东西不记录下来总是会忘的! 本文首先会分析eureka中的缓存架构.并 ...
- Kafka 系列(四)—— Kafka 消费者详解
一.消费者和消费者群组 在 Kafka 中,消费者通常是消费者群组的一部分,多个消费者群组共同读取同一个主题时,彼此之间互不影响.Kafka 之所以要引入消费者群组这个概念是因为 Kafka 消费者经 ...
- 【雕爷学编程】Arduino动手做(16)---数字触摸传感器
37款传感器和模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器与模块,依照实践出真知(动手试试)的理念,以学习和交流为目的,这里准备 ...
- Windows 10“数字权利激活”永久性激活!!!
直接运行软件即可自动激活,等出现"激活成功"即可关闭软件. 注意事项: 激活软件不会帮你打开Windows update服务,如关闭系统自动更细服务的需要先启动服务. 可以在小娜搜 ...
- 二阶段js 入门知识点 自我总结复习
二阶段自我总复习 1.javascript基础 : 客户端 安全性 跨平台 脚本语言 三大结构: 顺序 .选择.循环 顺序:运算符和表达式 ...
- iNeuOS 物联网云操作系统2.0发布,集成设备容器、视图建模、机器学习三大模块
目 录 1. 概述... 2 2. 使命及目标... 3 3. 系统框架... 4 4. 设备容器(iNeuKernel)... 4 5. ...
- Eclipse中安装JRebel热部署教程
Eclipse中安装JRebel热部署教程 前言 Eclipse安装JRebel插件可快速实现热部署,节省了大量重启时间,提高开发效率. 本文只介绍Eclipse安装JRebel插件版本 ...