linux物理内存管理:node,zone,page

一、总览

对于物理内存内存,linux对内存的组织逻辑从上到下依次是:node,zone,page,这些page是根据buddy分配算法组织的,看下面两张图:

上面的概念做下简单的介绍:

  • Node:每个CPU下的本地内存节点就是一个Node,如果是UMA架构下,就只有一个Node0,在NUMA架构下,会有多个Node
  • Zone:每个Node会划分很多域Zone,大概有下面这些:
  • ZONE_DMA:定义适合DMA的内存域,该区域的长度依赖于处理器类型。比如ARM所有地址都可以进行DMA,所以该值可以很大,或者干脆不定义DMA类型的内存域。而在IA-32的处理器上,一般定义为16M。
  • ZONE_DMA32:只在64位系统上有效,为一些32位外设DMA时分配内存。如果物理内存大于4G,该值为4G,否则与实际的物理内存大小相同。
  • ZONE_NORMAL:定义可直接映射到内核空间的普通内存域。在64位系统上,如果物理内存小于4G,该内存域为空。而在32位系统上,该值最大为896M。
  • ZONE_HIGHMEM:只在32位系统上有效,标记超过896M范围的内存。在64位系统上,由于地址空间巨大,超过4G的内存都分布在ZONE_NORMA内存域。
  • ZONE_MOVABLE:伪内存域,为了实现减小内存碎片的机制。
  • 分配价值链
    • 除了只能在某个区域分配的内存(比如ZONE_DMA),普通的内存分配会有一个“价值”的层次结构,按分配的“廉价度”依次为:ZONE_HIGHMEM > ZONE_NORMAL > ZONE_DMA。
    • 即内核在进行内存分配时,优先从高端内存进行分配,其次是普通内存,最后才是DMA内存
  • Page:zone下面就是真正的内存页了,每个页基础大小是4K,他们维护在一个叫free_area的数组结构中
    • order:数组的index,也叫order,实际对应的是page的大小,比如order为0,那么就是一堆1个空闲页(4K)组成的链表,order为1,就是一堆2个空闲页(8K)组成的链表,order为2,就是一堆4个空闲页(16K)组成的链表

二、源码分析

内存节点结构体在linux内核include/linux/mmzone.h文件

levelstructdesc
nodestruct pglist_data

NUMA下每个node由一个pglist_data结构体描述

UMA下只有一个node,即全局变量struct pglist_data contig_page_data;

zonestruct zone每个node下的物理内存被划分为不同zone,体现不同用途。整个系统里可能只有几个struct zone
pagestruct page描述每个物理页(page frame)的结构,每个物理页都有一个struct page,寸土寸金。

2.1、 struct pglist_data

mmzone.h - include/linux/mmzone.h - Linux source code v5.4.285 - Bootlin Elixir Cross Referencer

每个NUMA node对应一个struct pglist_data结构体,一些重要成员有:

nametypedesc
node_zonesstruct zone数组,长度为MAX_NR_ZONES该node下的zone。数组长度虽然是MAX_NR_ZONES,但是不代表当前node的实际zone数目就是MAX_NR_ZONES。实际的数量用nr_zones表示
node_zonelistsstruct zonelist数组,长度为MAX_ZONELISTS内存分配器在分配内存时,按照一定的策略遍历不同的内存区域,以找到合适的内存块。不同的内存区域可能有不同的属性(dma,normal,high等),node_zonelists帮助内存分配器根据需求选择合适的区域
nr_zonesint该node下实际zone的数量
node_start_pfnunsigned long longnode的起始pfn号,起始的物理地址
node_present_pagesunsigned long longnode实际包括的page数目(不含空洞)
node_spanned_pagesunsigned long long

node横跨的page数目(包括空洞)

kswapd

struct task_struct *

每个node都有一个kswapd线程,用于回收不经常使用的页面或者内存不足时回收内存
kswapd_waitstruct wait_queue_head kswapd_wait表示是一个kswapd等待队列,里面存放的是等待kswapd线程执行异步回收的线程,在free_area_init_core 函数中被初始化。

pfmemalloc_wait

struct wait_queue_head

 表示等待直接内存回收(direct reclaim)结束的线程等待队列。里面存放的都是等待由kswapd帮忙做完直接内存回收的线程。当kswapd直接内存回收后,整个node的free pages满足要求时,在kswapd睡眠前,kswapd会唤醒pfmemalloc_wait里面的线程,线程直接进行内存分配,这个等待队列的线程跳过了自己direct reclaim的操作。

kswapd_order

int表示kswapd线程内存回收的单位(2^kswapd_order),要求大于线程内存分配所需求的order,否则会更新为线程内存分配对应的order。
node_mem_map;

struct page *

当前node中所有struct page构成的mem_map数组

 常见的zone类型有:

  • ZONE_DMA,一些设备地址线数目有限(如24位),进行DMA时只能使用低地址(如<16MB),划分出ZONE_DMA防止低地址的页被分出去导致设备无法进行DMA。
  • ZONE_DMA32,64位系统下,区分支持32位地址线和24位地址线的DMA设备。
  • ZONE_NORMAL,一般内存处于这个zone区域。
  • ZONE_HIGHMEM,32位系统虚拟地址空间太小,只有1G给内核态,因此只能映射最多1G物理内存。高端内存区用于建立到物理地址的临时映射,使内核态可以寻址更多物理地址。64位架构下虚拟地址空间足够大,不需要这个zone。
enum zone_type {
#ifdef CONFIG_ZONE_DMA/** ZONE_DMA is used when there are devices that are not able* to do DMA to all of addressable memory (ZONE_NORMAL). Then we* carve out the portion of memory that is needed for these devices.* The range is arch specific.** Some examples** Architecture		Limit* ---------------------------* parisc, ia64, sparc	<4G* s390, powerpc	<2G* arm			Various* alpha		Unlimited or 0-16MB.** i386, x86_64 and multiple other arches* 			<16M.*/ZONE_DMA,
#endif
#ifdef CONFIG_ZONE_DMA32/** x86_64 needs two ZONE_DMAs because it supports devices that are* only able to do DMA to the lower 16M but also 32 bit devices that* can only do DMA areas below 4G.*/ZONE_DMA32,
#endif/** Normal addressable memory is in ZONE_NORMAL. DMA operations can be* performed on pages in ZONE_NORMAL if the DMA devices support* transfers to all addressable memory.*/ZONE_NORMAL,
#ifdef CONFIG_HIGHMEM/** A memory area that is only addressable by the kernel through* mapping portions into its own address space. This is for example* used by i386 to allow the kernel to address the memory beyond* 900MB. The kernel will set up special mappings (page* table entries on i386) for each page that the kernel needs to* access.*/ZONE_HIGHMEM,
#endifZONE_MOVABLE,
#ifdef CONFIG_ZONE_DEVICEZONE_DEVICE,
#endif__MAX_NR_ZONES};

2.2、 struct zone

mmzone.h - include/linux/mmzone.h - Linux source code v5.4.285 - Bootlin Elixir Cross Referencer

zone通过pfn和一些计数器描述它管理的物理地址空间:

  • zone_start_pfn,该zone所描述空间的起始页号。
  • spanned_pages,整个空间(包括空洞)占据的物理页数目,它等于zone_end_pfn - zone_start_pfn
  • present_pages,存在于空间中的物理页数目,等于spanned_pages减掉空洞中的页数目。
  • managed_pages,被buddy system管理的页数目,等于present_pages减掉被zone预留做其他用途的页数目。
  • struct free_area free_area[MAX_ORDER]buddy system使用的空闲链表,是一个per zone的结构。它直接存储了指向struct page*的指针。(详细见:伙伴(buddy)系统原理_伙伴系统算法-CSDN博客)
  • unsigned long _watermark[NR_WMARK]:内存水位值,分别为WMARK_MIN, WMARK_LOW, WMARK_HIGH水位,这在页面分配器和kswapd页面回收中会用到。
  • long lowmem_reserve[MAX_NR_ZONES]:zone中预留的内存。在内存分配时,高区的内存不足可以向低区的内存申请。reserve内存是确保在内存紧张的时候,仍然保留一定数量的低区内存,确保高区内存不会完全耗尽低区内存资源。

 2.3、 struct page

mm_types.h - include/linux/mm_types.h - Linux source code v5.4.285 - Bootlin Elixir Cross Referencer

这是一个特别复杂的结构,里面有很多的 union,这里之所以用了 union,是因为一个物理页面使用模式有两种。第一种模式,仅需分配小块内存,Linux 系统采用了一种被称为 slab allocator的技术。第二种模式,要用就用一整页。这一整页的内存,或者直接和虚拟地址空间建立映射关系,我们把这种称为匿名页(Anonymous Page)。或者用于关联一个文件,然后再和虚拟地址空间建立映射关系,这样的文件,我们称为内存映射文件(Memory-mapped File)。

每个物理页对应一个page结构体,称为页描述符,内存节点的pglist_data实例的成员node_mem_map指向该内存节点包含的所有物理页的页描述符组成的数组。

一些重要成员有:

nametypedesc
flagsunsigned longenum pgdat_flags 可以指示节点的状态或特定的内存管理属性。以便在内存分配、回收和其他操作中做出相应的决策。
以下是一些常见的 pgdat_flags 标志:
PGDAT_CONGESTED:表示该节点的内存可能处于拥塞状态。
PGDAT_WRITEBACK:表示该节点的内存正在进行写回操作。
PGDAT_RECLAIM_LOCKED:表示该节点的内存回收操作被锁定。
 

三、建立与初始化过程

ref:

Linux内存管理-1 | Do not touch fish!

Linux内存初始化(3)——pglist_data/zone初始化_linux struct page结构初始化-CSDN博客

Linux 物理内存管理涉及的三大结构体之struct pglist_data_linux的三种内存模型-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/10678.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

STM32-Flash闪存

目录 一、简介 1、闪存模块组织 2、FLASh基本结构 3、FLash写入和读取操作 4、编程流程 5、选项字节格式 6、选项字节编程步骤 二、读写芯片内部FLASH编程 三、器件电子签名 1、简介 2、编程实现 一、简介 STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节…

数据结构之带头双向循环链表

前言&#xff1a;前面我们实现了顺序表和单链表&#xff0c;这次来实现一个结构更复杂的链表-----带头双向循环链表。不要被它的名字吓到哦&#xff0c;只是结构复杂而已&#xff0c;它的结构更有利于代码的实现。 1 双向循环链表的介绍 有了单链表的基础&#xff0c;要实现这…

10个最常用的Python包,程序员必备!

世界上有超过200,000个Python程序包&#xff08;这只是基于官方的Python程序包索引PyPI托管的程序包&#xff09;。 这就引出了一个问题&#xff1a;拥有这么多的软件包&#xff0c;每个Python程序员都需要学习哪些软件包是最重要的&#xff1f; 为了帮助回答这个问题&#x…

线上问题的排查-java死锁问题如何排查

这里写目录标题 1.java死锁如何排查2.具体步骤1.1识别死锁现象1.2收集线程转储1.3分析线程转储1.4代码审查1.5重现问题1.6使用调试工具1.7.优化和验证 3. 解决方案总结 1.java死锁如何排查 在Java应用程序中&#xff0c;死锁是一个经典的并发问题&#xff0c;它会导致线程永久阻…

shodan(4-5)

以下笔记学习来自B站泷羽Sec&#xff1a; B站泷羽Sec 1. 查看自己的出口IP 可以知晓自己是哪个IP连接的公网 shodan myip2. 指定标题搜索 http.title:内容搜索被挂黑页的网页&#xff1a;获得标题中含有hacked by的IP shodan search --limit 10 --fields ip_str,port htt…

三种风格截然不同的实验室工控界面

三种风格截然不同的实验室工控界面各具特色。一种可能是简洁现代风&#xff0c;以简洁的线条、纯净的色彩和直观的图标&#xff0c;呈现出高效与专业。 另一种或许是科技未来风&#xff0c;运用炫酷的光影效果和立体感十足的设计&#xff0c;展现实验室的前沿科技感。 还有一…

Redis如何保证数据不丢失(可靠性)

本文主要以学习为主&#xff0c;详细参考&#xff1a;微信公众平台 Redis 保证数据不丢失的主要手段有两个&#xff1a; 持久化 多机部署 我们分别来看它们两的具体实现细节。 1.Redis 持久化 持久化是指将数据从内存中存储到持久化存储介质中&#xff08;如硬盘&#xf…

STM32F405RGT6单片机原理图、PCB免费分享

大学时机创比赛时画的板子&#xff0c;比到一半因为疫情回家&#xff0c;无后续&#xff0c;&#xff0c;&#xff0c;已打板验证过&#xff0c;使用stm32f405rgt6做主控 下载文件资源如下 原理图文件 pcb文件 外壳模型文件 stm32f405例程 功能 以下功能全部验证通过 4路…

“穿梭于容器之间:C++ STL迭代器的艺术之旅”

引言&#xff1a; 迭代器&#xff08;Iterator&#xff09;是C STL&#xff08;标准模板库&#xff09;中非常重要的一部分&#xff0c;它提供了一种统一的方式来遍历容器中的元素。无论容器是数组、链表、树还是其他数据结构&#xff0c;迭代器都能够以一致的方式访问这些数据…

jmeter常用配置元件介绍总结之用linux服务器压测

系列文章目录 安装jmeter jmeter常用配置元件介绍总结之用linux服务器压测 1.编写测试脚本2.执行测试脚本 1.编写测试脚本 在linux服务器上进行压测&#xff0c;由于是没有界面的&#xff0c;因此我们可以先在界面上把压测脚本写好&#xff1a; 如图&#xff1a;我这里简单的写…

Ubuntu 的 ROS 操作系统安装与测试

引言 机器人操作系统&#xff08;ROS, Robot Operating System&#xff09;是一个用于开发机器人应用的开源框架&#xff0c;它提供了一系列功能丰富的库和工具&#xff0c;能够帮助开发者构建和控制机器人。 当前&#xff0c;ROS1的最新版本为Noetic Ninjemys&#xff0c;专为…

计算机组成原理——编码与纠错(汉明编码)

校验码放在2^x次方的位置——即1&#xff0c;2&#xff0c;4——将检测位按序排列p3p2p1 汉明编码从左到右数某个位置位1&#xff08;位数&#xff09;&#xff0c;就表示第几组 奇偶校验 例题 纠错过程 汉明编码的最小距离是3

fabric操作canvas绘图(1)共32节

对于前端而言&#xff0c;离不开canvas就像鱼离不开水&#xff0c;前端canvas神器fabric你值得拥有&#xff01;接下来我们就来一步步揭开她的面纱。 一、fabric的理解 用原生的canvas来实现&#xff0c;代码量会比较大&#xff0c;而且还要处理很多细节&#xff0c;而Fabric…

C++ 内存分布及 new , delete 分配问题( ~~~ 面试重要 ~~~)

文章目录 前言一、内存分布二、new 、delete 分配问题总结 前言 本篇文章笔者将会对 C 中的内存问题简单的讲解 , 同时对 new , delete 的面试题进行重点讲解. 一、内存分布 ● C语言和C 分布情况是一样的, 如下 : ● 栈 ○ 栈 的管理是由编译器自动管理 , 不需要我们人为做…

数据结构-哈夫曼树

一.什么是哈夫曼树 不同搜索树的效率是不一样的,根据不同的频率构造效率比较好或者最好的搜索树就是哈夫曼树 二.哈夫曼树的定义 将带权路径的长度降低最低 每个叶子节点到根节点的距离乘权值&#xff0c;再全都加起来就得到了WPL值 第一颗二叉树:从上到下计算 5x14x23x32x41…

双11精选网络安全书单:打造数字世界的钢铁长城!

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 &#x1f31f;双11火热来袭&#xff0c;网络安全书单推荐&#x1f680; 随着数字化浪潮的汹涌澎湃&#xff0c;网络安全已经成为了每个从业者不可回避的重要议…

WebGUI之Gradio:Gradio 5的简介、安装和使用方法、案例应用之详细攻略

WebGUI之Gradio&#xff1a;Gradio 5的简介、安装和使用方法、案例应用之详细攻略 目录 Gradio 5的简介 1、Gradio的适用场景 2、Gradio 5 的主要改进包括&#xff1a; Gradio 5的安装和使用方法 1、安装和使用方法 2、使用方法 2.1、文本内容 (1)、简单的输入/输出组件…

初始Python篇(5)—— 集合

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; Python 目录 集合 相关概念 集合的创建与删除 集合的操作符 集合的相关操作方法 集合的遍历 集合生成式 列表、元组、字典、集合的…

探索Python的Shell力量:Plumbum库揭秘

文章目录 探索Python的Shell力量&#xff1a;Plumbum库揭秘第一部分&#xff1a;背景介绍第二部分&#xff1a;Plumbum是什么&#xff1f;第三部分&#xff1a;如何安装Plumbum&#xff1f;2. 创建管道3. 重定向4. 工作目录操作5. 前台和后台执行 第五部分&#xff1a;场景应用…

大模型时代,算法岗到底哪个最有前景?什么样的算法工程师更吃香?

毫无疑问&#xff0c;全栈型的算法工程师将更为抢手&#xff0c;如果你精通大模型从训练到应用的整个流程&#xff0c;你走到哪里都不怕。 但往往人的精力有限&#xff0c;如果从数据、预训练、微调、对齐、推理、应用几个方面来看的话&#xff0c;个人觉得 “预训练>数据&…