底层开发必知的三个内存结构概念

简介: 底层开发必知的三个内存结构概念

Linux中内存管理子系统使用节点(node)、区域(zone)和页(page)三级结构描述物理内存。

内存节点

内存节点分两种情况:UMANUMA

从管理内存的方法上区分,计算机可以分为两种类型:UMANUMA

UMA:一致性内存访问,uniform memory access

NUMA:非一致性内存访问,non-uniform memory access

两种类型示意图:

UMA来说,每一个CPU 访问的都是同一块内存,因此各CPU对内存的访问不存在性能差异

NUMA来说,各内存和各CPU通过总线连在一起,每个CPU都有一个本地内存,访问速度快,CPU也可以访问其他CPU的本地内存,但速度稍慢

Linux为了统一这两种平台,在内存组织中,将最高层次定义为内存节点.

可以看到,图中UMA只有一个内存节点,而NUMA有两个内存节点。

实际上,UMA其实是NUMA的一个特例,所以内核可以将内存都看做NUMA类型的。

区域

每个内存节点都划分为多个区,Linux内核中定义了以下几个区:

include/linux/mmzone.h

enum zone_type{
#ifdef CONFIG_ZONE_DMA
 ZONE_DMA,
#endif
#ifdefi CONFIG_ZONE_DMA32
 ZONE_DMA32,
#endif
 ZONE_NORMAL,
#ifdef CONFIG_HIGHMEM
 ZONE_HIGHMEM,
#endif
 ZONE_MOVABLE,
#ifdef CONFIG_ZONE_DEVICE
 ZONE_DEVICE,
#endif
 __MAX_NR_ZONES
};

ZONE_DMA

DMA是“Direct Memory Access”的缩写,直接内存访问。

该区域用于ISA设备的DMA操作,范围是0-16MB。

如果有些设备不能直接访问所有内存,则需要使用DMA区域。例如旧的工业标准体系结构(Industry Standard Architecture, ISA)总线只能直接访问16MB以下的内存。

只适用于Intel x86架构,ARM架构没有这个内存管理区。

ZONE_DMA32

在64位的系统上使用32位地址寻址的适合DMA操作的内存区。

例如在AMD64系统上,该区域为低4GB的空间。在32位系统上,本区域通常是空的。

ZONE_NORMAL

常规内存区,指的是可以直接映射到内核空间的内存。

也常称为“普通区域”“直接映射区域”“线性映射区域”。

所谓线性映射就是物理地址和映射后的虚拟地址存在一种简单的关系,即虚拟地址=物理地址+固定偏移

在32位系统上,内核空间和用户空间按1:3划分,那么这个固定偏移就是:0xC0000000 - 物理内存起始地址

既然存在一种线性关系,那还需要使用页表对物理地址和虚拟地址做映射吗?

不同处理器架构实现不一样,ARM需要使用页表映射,MIPS则不需要。

ZONE_HIGHMEM

高端内存区,32位时代的产物。在32位系统上,指的是高于896M的物理内存。

32位系统中,内核和用户地址空间按1:3划分,内核地址空间只有1GB,所以不能把1GB以上的内存直接映射到内核地址空间,因此就把不能直接映射的内存划分到了高端内存区。

要将高于896MB的物理内存映射在内核空间的话,需要通过单独的映射来完成,并且这类映射不能保证物理地址和虚拟地址之间存在固定的对应关系(例如ZONE_NORMAL的固定偏移)。

ZONE_DMA、ZONE_DMA32、ZONE_NORMAL通常都统称为低端内存区。

64位系统中没有这个区域,即没有高端内存。因为64系统的内核虚拟地址空间非常大,不再需要高端内存区域。

ZONE_MOVABLE

一个伪内存区,用来防止内存碎片。

ZONE_DEVICE

为支持持久内存(persistent memory)热拔插增加的内存区域

站在处理器的角度来看,管理物理内存的最小单位是页面。

现在的处理器都采用分页机制来管理内存,在处理器内部有一个MMU硬件,它会处理虚拟内存到物理内存的映射,也就是做页表的翻译工作。

Linux内核中使用一个page数据结构来描述一个物理页面。

页的大小通常是4KB,但有个的架构的处理器可以支持大于4KB的页,例如8KB16KB或者64KB的页。

目前Linux内核默认使用4KB的页面。

所以,Linux内核的用三级结构来管理物理内存,简言之就是内存首先划分成若干个大的节点,每个节点又包含若干个区,每个区有包含若干页。Linux内核按页管理内存,最基本的内存分配和释放都是按页进行的。

end

往期推荐

直到我干了底层开发,才知道不写业务代码有多爽

你解决bug的能力,暴露了你的水平

入职Linux驱动工程师后,我才知道的真相......

很底层的性能优化:让CPU更快地执行你的代码

薪资倒挂,大家都沉默了...

机遇:我是如何走向Linux驱动的...

当我用几道题考了一遍做Linux驱动的同事......

相关文章
|
5月前
|
存储 Java 编译器
深入理解JVM系列教程(02) - Java内存结构
深入理解JVM系列教程(02) - Java内存结构
146 0
|
1月前
|
缓存 Java Android开发
安卓应用开发中的内存优化策略
在移动应用开发领域,性能一直是衡量应用质量的重要指标之一。特别是对于安卓平台,由于设备的硬件配置多样化,内存管理成为开发者面临的重大挑战。本文将深入探讨针对安卓平台的内存优化技巧,包括内存泄漏的预防、合理使用数据结构和算法、以及高效的资源释放机制。通过这些方法,开发者可以显著提升应用的性能和用户体验。
|
1月前
|
监控 算法 Android开发
安卓应用开发中的内存优化策略
【2月更文挑战第30天】随着移动设备性能的不断提升,用户对应用程序的体验要求越来越高。在安卓应用开发中,内存管理是影响应用性能和用户体验的关键因素之一。本文将探讨针对安卓平台的内存优化技巧,包括避免内存泄漏、合理使用数据结构和算法、优化图片资源处理等策略,旨在帮助开发者提升应用性能和稳定性。
19 1
|
1月前
|
消息中间件 Linux
Linux进程间通信(IPC)教程 Linux共享内存介绍:介绍POSIX共享内存的基本概念、用途和编程实践
Linux进程间通信(IPC)教程 Linux共享内存介绍:介绍POSIX共享内存的基本概念、用途和编程实践
25 2
|
1月前
|
存储 Java C++
JVM内存模型和结构详解(五大模型图解)
JVM内存模型和结构详解(五大模型图解)
|
6月前
|
存储 编译器 C语言
结构体类型的结构在内存的存储
结构体类型的结构在内存的存储
|
3月前
|
网络协议
Reactor学习,从数据结构,内存分配,概念上分析
Reactor学习,从数据结构,内存分配,概念上分析
38 0
|
4月前
|
存储 缓存 算法
JVM【带着问题去学习 01】什么是JVM+内存结构+堆内存+堆内存参数(逃逸分析)
JVM【带着问题去学习 01】什么是JVM+内存结构+堆内存+堆内存参数(逃逸分析)
33 0
|
4月前
|
存储 前端开发 Java
深入解析JVM内存结构:Metaspace、堆与垃圾收集器
深入解析JVM内存结构:Metaspace、堆与垃圾收集器
|
4月前
|
存储 安全 数据安全/隐私保护
3.2 Windows驱动开发:内核CR3切换读写内存
CR3是一种控制寄存器,它是CPU中的一个专用寄存器,用于存储当前进程的页目录表的物理地址。在x86体系结构中,虚拟地址的翻译过程需要借助页表来完成。页表是由页目录表和页表组成的,页目录表存储了页表的物理地址,而页表存储了实际的物理页框地址。因此,页目录表的物理地址是虚拟地址翻译的关键之一。在操作系统中,每个进程都有自己的地址空间,地址空间中包含了进程的代码、数据和堆栈等信息。为了实现进程间的隔离和保护,操作系统会为每个进程分配独立的地址空间。在这个过程中,操作系统会将每个进程的页目录表的物理地址存储在它自己的CR3寄存器中。当进程切换时,操作系统会修改CR3寄存器的值,从而让CPU使用新的页
57 0
3.2 Windows驱动开发:内核CR3切换读写内存