内核解读之内存管理(2)内存管理三级架构之内存结点node

news2024/10/4 12:56:27

文章目录

    • 0、概述
    • 1、内存节点node

0、概述

结合NUMA的架构,Linux抽象出了三级内存管理架构:内存节点node、内存区域zone和物理页框page。

在NUMA模型中,每个CPU都有自己的本地内存节点(memory node),而且还可以通过QPI总线访问其他CPU下挂的内存节点,只是访问本地内存要比访问其他CPU下的内存的速度高许多,一般经过一次QPI要增加30%的访问时延。

内存节点node是为了解决多处理器内存访问竞争的问题,而内存区域zone是为了解决32位系统内核只有1G的虚拟地址空间,无法管理大于1G的物理内存这个问题,zone按照用途划分成几种类型,比如低端内存区,高端内存区,DMA内存区等。

图片

内核内存管理三级架构

1、内存节点node

NUMA结构下, 每个处理器与一个本地内存直接相连, 而不同处理器之间则通过总线进行进一步的连接。linux内核把物理内存按照CPU节点划分为不同的node, 每个node作为某个cpu结点的本地内存, 而作为其他CPU节点的远程内存, 而UMA结构下, 则任务系统中只存在一个内存node, 这样对于UMA结构来说, 内核把内存当成只有一个内存node节点的伪NUMA。因此,NUMA和UMA的管理方式便一致了。

Linux内核中使用数据结构pg_data_t来表示内存节点node,我们把它叫做结点描述符。如常用的ARM架构为UMA架构。对于UMA架构只有一个内存节点,对于NUMA架构有多个内存节点。

在numa.h中有如下定义:

#ifdef CONFIG_NODES_SHIFT
#define NODES_SHIFT     CONFIG_NODES_SHIFT
#else
#define NODES_SHIFT     0
#endif

#define MAX_NUMNODES    (1 << NODES_SHIFT)

CONFIG_NODES_SHIFT是由用户配置的内存节点的数目。可以看到,对于UMA架构,MAX_NUMNODES等于1。

include/linux/mmzone.h:

/*
 * On NUMA machines, each NUMA node would have a pg_data_t to describe
 * it's memory layout. On UMA machines there is a single pglist_data which
 * describes the whole memory.
 *
 * Memory statistics and page replacement data structures are maintained on a
 * per-zone basis.
 */
typedef struct pglist_data {
	/*
	 * node_zones contains just the zones for THIS node. Not all of the
	 * zones may be populated, but it is the full list. It is referenced by
	 * this node's node_zonelists as well as other node's node_zonelists.
	 */
	struct zone node_zones[MAX_NR_ZONES];
    /* node_zones是一个数组,包含节点中各内存区(ZONE_DMA, ZONE_DMA32, ZONE_NORMAL...)的描述符。*/

	/*
	 * node_zonelists contains references to all zones in all nodes.
	 * Generally the first zones will be references to this node's
	 * node_zones.
	 */
	struct zonelist node_zonelists[MAX_ZONELISTS]; /* 指定了节点的备用zone列表 */
   
/*

struct zonelist {
	struct zoneref _zonerefs[MAX_ZONES_PER_ZONELIST + 1];
}

该结构包含了类型为 struct zoneref 的一个备用列表,由于该备用列表必须包括所有结点的所有内存域,因此由 MAX_NUMNODES * MAX_NZ_ZONES 项组成,外加一个用于标记列表结束的空指针。

/* Maximum number of zones on a zonelist */
#define MAX_ZONES_PER_ZONELIST (MAX_NUMNODES * MAX_NR_ZONES)

/*
 * This struct contains information about a zone in a zonelist. It is stored
 * here to avoid dereferences into large structures and lookups of tables
 */
struct zoneref {
	struct zone *zone;	/* Pointer to actual zone */
	int zone_idx;		/* zone_idx(zoneref->zone) */
};

*/
    
    
	int nr_zones; /* number of populated zones in this node */ /*指示了节点中zone的数目*/
#ifdef CONFIG_FLATMEM	/* means !SPARSEMEM */
	struct page *node_mem_map; /* 平铺式内存模式下,物理page数组,linux为每个物理页分配了一个struct page的管理结构体,并形成了一个结构体数组,node_mem_map即为数组的指针;pfn_to_page和page_to_pfn都借助该数组实 */
#ifdef CONFIG_PAGE_EXTENSION
	struct page_ext *node_page_ext;
#endif
#endif
#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_DEFERRED_STRUCT_PAGE_INIT)
	/*
	 * Must be held any time you expect node_start_pfn,
	 * node_present_pages, node_spanned_pages or nr_zones to stay constant.
	 * Also synchronizes pgdat->first_deferred_pfn during deferred page
	 * init.
	 *
	 * pgdat_resize_lock() and pgdat_resize_unlock() are provided to
	 * manipulate node_size_lock without checking for CONFIG_MEMORY_HOTPLUG
	 * or CONFIG_DEFERRED_STRUCT_PAGE_INIT.
	 *
	 * Nests above zone->lock and zone->span_seqlock
	 */
	spinlock_t node_size_lock;
#endif
	unsigned long node_start_pfn;   /* 节点第一页帧逻辑编号 */
	unsigned long node_present_pages; /* total number of physical pages */ /* 节点中物理页帧总数目 */
	unsigned long node_spanned_pages; /* total size of physical page
					     range, including holes */   /* 按照平铺计算的节点物理页帧总数目。由于空洞的存在可能不等于node_present_pages,应该是大于等于node_present_pages。*/
	int node_id; /*结点id*/
	wait_queue_head_t kswapd_wait; /* kswapd页换出守护进程使用的等待队列 */
	wait_queue_head_t pfmemalloc_wait;

	/* workqueues for throttling reclaim for different reasons. */
	wait_queue_head_t reclaim_wait[NR_VMSCAN_THROTTLE];

	atomic_t nr_writeback_throttled;/* nr of writeback-throttled tasks */
	unsigned long nr_reclaim_start;	/* nr pages written while throttled
					 * when throttling started. */
#ifdef CONFIG_MEMORY_HOTPLUG
	struct mutex kswapd_lock;
#endif
	struct task_struct *kswapd;	/* Protected by kswapd_lock */ /* 指针指向kswapd内核线程的进程描述符 */
    /* 每个结点都有一个内核进程kswapd,它的作用就是将进程或内核持有的,但是不常用的页交换到磁盘上,以腾出更多可用内存。不信你可以ps看一下。*/
	int kswapd_order; /* 需要释放的区域的长度,以页阶为单位 */
	enum zone_type kswapd_highest_zoneidx;

	int kswapd_failures;		/* Number of 'reclaimed == 0' runs */

#ifdef CONFIG_COMPACTION
	int kcompactd_max_order;
	enum zone_type kcompactd_highest_zoneidx;
	wait_queue_head_t kcompactd_wait;
	struct task_struct *kcompactd;
	bool proactive_compact_trigger;
#endif
	/*
	 * This is a per-node reserve of pages that are not available
	 * to userspace allocations.
	 */
	unsigned long		totalreserve_pages;

    /* 结点page回收相关 */
#ifdef CONFIG_NUMA
	/*
	 * node reclaim becomes active if more unmapped pages exist.
	 */
	unsigned long		min_unmapped_pages;
	unsigned long		min_slab_pages;
#endif /* CONFIG_NUMA */

	/* Write-intensive fields used by page reclaim */
	CACHELINE_PADDING(_pad1_);

#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
	/*
	 * If memory initialisation on large machines is deferred then this
	 * is the first PFN that needs to be initialised.
	 */
	unsigned long first_deferred_pfn;
#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
	struct deferred_split deferred_split_queue;
#endif

#ifdef CONFIG_NUMA_BALANCING
	/* start time in ms of current promote rate limit period */
	unsigned int nbp_rl_start;
	/* number of promote candidate pages at start time of current rate limit period */
	unsigned long nbp_rl_nr_cand;
	/* promote threshold in ms */
	unsigned int nbp_threshold;
	/* start time in ms of current promote threshold adjustment period */
	unsigned int nbp_th_start;
	/*
	 * number of promote candidate pages at stat time of current promote
	 * threshold adjustment period
	 */
	unsigned long nbp_th_nr_cand;
#endif
	/* Fields commonly accessed by the page reclaim scanner */

	/*
	 * NOTE: THIS IS UNUSED IF MEMCG IS ENABLED.
	 *
	 * Use mem_cgroup_lruvec() to look up lruvecs.
	 */
	struct lruvec		__lruvec;

	unsigned long		flags; /* 结点标记 */

#ifdef CONFIG_LRU_GEN
	/* kswap mm walk data */
	struct lru_gen_mm_walk	mm_walk;
#endif

	CACHELINE_PADDING(_pad2_);

	/* Per-node vmstats */
	struct per_cpu_nodestat __percpu *per_cpu_nodestats;
	atomic_long_t		vm_stat[NR_VM_NODE_STAT_ITEMS];
#ifdef CONFIG_NUMA
	struct memory_tier __rcu *memtier;
#endif
} pg_data_t;

在UMA结构的机器中, 只有一个node结点contig_page_data, 此时NODE_DATA直接指向了全局的contig_page_data, 而与node的编号nid无关,其中全局唯一的内存node结点contig_page_data定义在include/linux/mmzone.h:。

#ifndef CONFIG_NUMA

extern struct pglist_data contig_page_data;
static inline struct pglist_data *NODE_DATA(int nid)
{
	return &contig_page_data;
}

#else /* CONFIG_NUMA */

#include <asm/mmzone.h>

#endif /* !CONFIG_NUMA */

定义了NUMA时,NUMA和平台相关,截取arm64的定义如下:

arch/arm64/include/asm/mmzone.h:

/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_MMZONE_H
#define __ASM_MMZONE_H

#ifdef CONFIG_NUMA

#include <asm/numa.h>

extern struct pglist_data *node_data[];
#define NODE_DATA(nid)		(node_data[(nid)])

#endif /* CONFIG_NUMA */
#endif /* __ASM_MMZONE_H */

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

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

相关文章

qq录制视频保存到哪了?如何更改qq录屏存储位置

一、查看qq录制视频保存位置如果有录制视频的需求&#xff0c;相信大部分人都是使用qq自带的录屏功能来录制视频。那qq录屏后的视频在哪里去找&#xff1f;今天就给大家分享如何查看qq录制完的视频保存位置操作方法&#xff1a;第一步&#xff1a;电脑上登录qq&#xff0c;在qq…

Cadence PCB仿真 使用Allegro PCB SI为BRD文件创建通用型IBIS模型的方法图文教程

⏪《上一篇》   🏡《总目录》   ⏩《下一篇》 1,概述 本文简单介绍使用Allegro PCB SI软件为BRD PCB设计文件中的元器件创建IBIS模型的方法。 2,创建方法 第1步:确定打开PCB文件的软件是 Allegro PCB SI 如果不是Allegro PCB SI,可执行File→Change Editor…更换软…

尚医通-查询所有子节点-前端整合-更新医院状态(二十三)

目录&#xff1a; &#xff08;1&#xff09;医院管理-查询所有子节点接口 &#xff08;2&#xff09;医院列表-前端整合 &#xff08;3&#xff09;更新医院上线状态-功能实现 &#xff08;1&#xff09;医院管理-查询所有子节点接口 先做一个省的查询 在DictContrlller…

数据可视化大屏百度地图GPS轨迹位置感知状态开发实战案例解析(包含缩放控件、点线覆盖物、弹窗、标注图标分类功能)

系列文章目录 1.数据可视化大屏应急管理综合指挥调度系统完整案例详解&#xff08;PHP-API、Echarts、百度地图&#xff09; 2.数据可视化大屏百度地图API开发&#xff1a;停车场分布标注和检索静态版 3.百度地图高级开发&#xff1a;map.getDistance计算多点之间的距离并输入…

C语言及算法设计课程实验三:最简单的C程序设计——顺序程序设计(二)

C语言及算法设计课程实验三&#xff1a;最简单的C程序设计——顺序程序设计&#xff08;二&#xff09;一、实验目的二、 实验内容2.2、实验内容2&#xff1a;求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积三、 实验步骤3.2、顺序程序设计实验题目2&#xff1a;求圆周长、…

CTF文件隐写总结之图片

1.1 Fastjson反序列化 代码审计 本项目引入的Fastjson版本为1.2.58&#xff0c;该版本存在反序列化漏洞。 已确定了Fastjson版本存在问题&#xff0c;进一步寻找触发Fastjson的漏洞点。 我们关注两个函数JSON.parse()和JSON.parseObject(),并且执行函数内参数用户可控 Edi…

【博客系统】后台设计

文章目录博客系统&#xff08;使用模板技术&#xff09;准备工作数据库设计表设计文章表用户表完整SQL封装数据库操作代码创建DBUtil创建Blog类和User类创建BlogDao类和UserDao类实现insert实现selectAll实现selectOne实现delete实现selectByName实现selectByUserId验证数据库代…

Python 操作 MySQL 之 pysql 与 SQLAchemy

一、pymsql pymsql 是 Python 中操作 MySQL 的原生模块&#xff0c;其使用方法和 MySQL 的SQL语句几乎相同 1、下载安装 pip3 install pymysql 2、执行SQL 执行 SQL 语句的基本语法&#xff1a; 需要注意的是&#xff1a;创建链接后&#xff0c;都由游标来进行与数据库的…

CATCTF wp

文章目录ez_jsCat_Jumpmiao~CatCatPeekabooMeowMeowCatchCatCatFlagNepnep 祝你新年快乐啦&#xff01;ez_js f12搜索score&#xff0c;修改超过分数1即可获得flag 然后获得flag地址 访问即可 Cat_Jump 仿真玩半天不知道怎么解&#xff0c;最后直接搜关键词出的 挺可惜…

唱歌就能画一幅图像? #whisper-to-stable-diffusion

现在热门的不仅是多模态的文本图像生成&#xff0c;前阵子&#xff0c;OpenAI 发布了一个自动语音识别系统 Whispe 。在处理口音、背景噪声以及技术术语方面&#xff0c;Whisper 几乎达到了人类的水准。那么将 Whisper 与 Stable Diffusion 结合&#xff0c;可以直接完成语音生…

回顾 OpenMLDB 2022 之旅 | 开源之路,行将致远

2022年初&#xff0c;OpenMLDB 尚且懵懂稚嫩。彼时的我们刚刚走过开源道路上的第一个秋天&#xff0c;还没有结出丰硕的果实。前进着&#xff0c;期待着&#xff0c;2022的一切徐徐展开&#xff1a; 请旋转手机 和 OpenMLDB 共同回忆 2022 之旅 2022年末&#xff0c;OpenMLDB …

必看!.NET 7 在网络领域的四大更新

最新的 .NET 7 现已发布&#xff0c;我们想介绍一下其在网络领域所做的一些有趣的更改和添加。这篇文章我们将讨论 .NET 7 在 HTTP 空间、新 QUIC API、网络安全和 WebSockets 方面的变化。 HTTP 改进了对连接尝试失败的处理 在 .NET 6 之前的版本中&#xff0c;如果连接池中…

云计算运营—04 FusionSphere OpenStack 6.5方案介绍

FusionSphere OpenStack 6.5方案介绍 OpenStack 系统架构 OpenStack是什么 OpenStack是目前最流行的开源云操作系统&#xff1a; 资源抽象 OpenStack将各类硬件资源&#xff0c;通过虚拟化与软件定义的方式&#xff0c;抽象成资源池 资源分配与负载调度 OpenStack根据管理员…

Ardupilot EKF3核心算法《状态量的协方差矩阵推导》

目录 文章目录 目录摘要1.协方差矩阵推导2.关于 F的计算2.1 计算F的前四维关于四元数的状态方程2.2 计算F 的5-10维关于速度和位置的状态方程3.其他协方差的传播3.1 关于角增量偏差的协方差传播3.2 关于速度增量偏差的协方差传播3.3 关于地理坐标系地磁磁场矢量的协方差传播3.4…

【Vue基本指令】一.什么是Vue;二.Vue开发的方式;三.Vue的基本指令(重点)

目录 一.什么是Vue 1.前端技术的发展&#xff08;html、CSS、JavaScript&#xff09; &#xff08;1&#xff09;JQuery&#xff1a;是对JavaScript进行了封装&#xff0c;使得操作DOM、事件处理、动画处理、Ajax交互变得非常简洁、方便。是JavaScript的库。 &#xff08;&a…

《云原生》一文搞懂RocketMQ队列概述

目录 序 概念简述 一、客户端概念 1. Topic-主题 2.ConsumerGroup&#xff08;消费者组&#xff09; 概念一览图 二、消息传输模型 三、实践应用 1.配置文件 2.生产者 3.消费者 配置一览图 最后的话 序 接上一篇对rabbitMQ队列进行了梳理 《一文搞懂rabbitMQ消息…

shell技术

退出状态码 Shell 中运行的命令会使用0-255之间的整数值&#xff0c;作为退出状态码,并以此来告知shell该命令执行的状态。 通常情况下&#xff0c;约定0代表命令成功结束&#xff0c;非0代表程序非正常退出。 假如没有指定返回值&#xff0c;那么会用脚本的最后一个命令的执…

华为路由器配置笔记

路由器(Router),是连接因特网中各局域网、广域网的设备,它会根据信道的情况自动选择和设定路由,以最佳路径,按前后顺序发送信号,路由器工作在网络层,用来跨网段通信,路由器具有判断网络地址和选择IP路径的功能,它能在多网络互联环境中,建立灵活的连接,可用完全不同的数据分组和…

巧用数据分析表达式,让数据指标创建更简单

实现数据业务一体化的指标分析 从零售系统进化史get 数据统计的需求变更 零售系统需要的数据统计需求 V1.0 只需要获取当日累计的销售额&#xff0c;于是店老板就用 Excel或者纸质的表格创建了一个表&#xff0c;表中包含销售的日期时间&#xff0c;销售的产品&#xff0c;销…

c语言的变量和指针,怎么理解?

学会应用指针是C语言程序员的分水岭&#xff0c;也是C程序员级别的试金石。 变量可以分为基础变量、数组变量、指针变量&#xff0c;其中数组变量非常特殊&#xff0c;可以进一步分为基础数组变量和指针数组变量&#xff0c;所以暂时不考虑数组变量。假设我们在32位计算机上工…