Linux 内核内存管理 pfn_to_online_page宏
文章目录
- 一、Memory Hotplug
- 1.1 简介
- 1.2 热插拔事件通知机制
- 二、pfn_to_online_page
- 2.1 pfn_to_online_page
- 2.2 pfn_to_section_nr
- 2.3 online_section_nr
- 参考资料
一、Memory Hotplug
1.1 简介
Linux 内存热插拔(Memory Hotplug)是指在运行时动态增加或移除物理内存模块,而不需要重新启动系统。这个功能允许管理员根据系统需要增加或减少内存容量,以满足应用程序的需求或进行硬件维护。
内存热插拔在服务器环境中尤为重要,因为它允许在不中断系统运行的情况下灵活地管理内存资源。
Linux 内核提供了内存热插拔的支持,具体包括以下方面:
(1)内存热插拔事件检测:内核通过硬件或固件接口检测到内存模块的插入或移除事件。这些事件通常通过总线、ACPI(高级配置与电源接口)或其他平台特定的机制进行通知。
(2)内存热插拔事件处理:一旦内核检测到内存插入或移除事件,它会启动相应的处理过程。这包括检测新插入的内存模块的属性和容量,并相应地更新内核的内存管理数据结构。
(3)内存段管理:内核将物理内存划分为多个内存段,每个内存段包含一定数量的物理页框。内存热插拔过程中,内核会根据内存模块的插入或移除来更新内存段的映射关系。
(4)内存热插拔事件通知:内核通过系统事件通知机制(如UEVENT)或文件系统接口(如/sys/devices/system/memory)向用户空间发送内存热插拔事件的通知。
(5)内存管理:内核通过内存热插拔支持可以动态地分配和释放新增的内存容量。这使得系统可以根据需要动态调整内存资源的分配,以提高性能和灵活性。
Linux 内存热插拔支持允许在运行时动态增加或移除物理内存模块,通过更新内核的内存管理数据结构和内存段映射关系,实现对内存资源的动态管理,并提供相应的事件通知机制,以便用户空间和应用程序可以响应内存热插拔事件。
1.2 热插拔事件通知机制
在 Linux 中,内存热插拔事件通知是通过以下机制之一向用户空间发送的:
(1)UEVENT:UEVENT 是 Linux 内核中一种通用的事件传递机制,用于向用户空间发送设备相关事件。内存热插拔事件通常以 UEVENT 的形式发送。当内核检测到内存插入或移除事件时,会生成相应的 UEVENT 消息,并通过 netlink 接口将该消息发送到用户空间。用户空间可以通过监听 netlink socket,并解析收到的 UEVENT 消息来获取内存热插拔事件相关的信息。
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
NETLINK_KOBJECT_UEVENT:提供内核广播 uevent 的接口,通常由 udev 使用,是内核通用模型向用户层发送信息所采用的协议(内核热插拔机制的基础)。
(2)sysfs 文件系统接口:Linux 内核提供了 sysfs 文件系统,其中包含了设备、驱动程序和其他内核对象的信息。对于内存热插拔事件,内核会在 sysfs 文件系统中相应的目录下创建或删除相应的文件或目录节点来表示内存的插入或移除。用户空间可以通过监视 sysfs 文件系统中相应的路径并检测文件或目录的创建或删除来获取内存热插拔事件的通知。
内存热插拔事件相关的信息通常位于 /sys/devices/system/memory 目录下。
这些机制提供了不同的接口和方式,供用户空间应用程序或守护进程监听和接收内存热插拔事件的通知。用户空间可以根据具体的需求选择适合的机制来接收和处理内存热插拔事件。
二、pfn_to_online_page
2.1 pfn_to_online_page
通常 pfn与 struct page 之间的转化都是 pfn_to_page 宏,这里介绍下pfn_to_online_page 宏。
# cat /boot/config-4.19.90-23.8.v2101.ky10.x86_64 | grep CONFIG_MEMORY_HOTPLUG
CONFIG_MEMORY_HOTPLUG=y
// linux-4.19.90/include/linux/memory_hotplug.h#ifdef CONFIG_MEMORY_HOTPLUG
/** Return page for the valid pfn only if the page is online. All pfn* walkers which rely on the fully initialized page->flags and others* should use this rather than pfn_valid && pfn_to_page*/
#define pfn_to_online_page(pfn) \
({ \struct page *___page = NULL; \unsigned long ___pfn = pfn; \unsigned long ___nr = pfn_to_section_nr(___pfn); \\if (___nr < NR_MEM_SECTIONS && online_section_nr(___nr) && \pfn_valid_within(___pfn)) \___page = pfn_to_page(___pfn); \___page; \
})
pfn_to_online_page用于获取 online 的 struct page 。
宏定义的实现逻辑如下:
(1)使用pfn_to_section_nr宏将___pfn转换为对应的内存段号(section number)。内存段是物理内存的分段单位。
(2)过online_section_nr函数判断内存段号___nr是否在线(online)。online_section_nr函数用于检查指定内存段号是否为在线状态。
(3)如果内存段号___nr小于总内存段数(NR_MEM_SECTIONS)并且该内存段号在线,并且___pfn在有效范围内(通过pfn_valid_within宏判断),则执行下面的代码块。
(4)在代码块中,通过pfn_to_page宏将___pfn转换为对应的struct page指针。
2.2 pfn_to_section_nr
// linux-4.19.90/include/linux/mmzone.h/* PFN_SECTION_SHIFT pfn to/from section number */
#define PFN_SECTION_SHIFT (SECTION_SIZE_BITS - PAGE_SHIFT)static inline unsigned long pfn_to_section_nr(unsigned long pfn)
{return pfn >> PFN_SECTION_SHIFT;
}
函数的实现逻辑非常简单,它使用位移操作符(>>)将物理页框号右移 PFN_SECTION_SHIFT 位,然后返回结果作为内存段号。
PFN_SECTION_SHIFT 是一个宏定义,表示物理页框号和内存段号之间的位移量。这个值是根据系统的物理内存布局和内存段的大小来确定的。
通过这个函数,可以将物理页框号转换为对应的内存段号,从而在内核中进行内存段相关的操作和管理。
备注:内存热插拔(Memory Hotplug):内存热插拔是指在运行时动态增加或移除物理内存模块。内核使用内存段号来管理和跟踪物理内存的热插拔操作。通过将物理页框号转换为对应的内存段号,内核可以准确地定位和操作要插入或移除的物理内存段。
其对应还有一个函数:
static inline unsigned long section_nr_to_pfn(unsigned long sec)
{return sec << PFN_SECTION_SHIFT;
}
2.3 online_section_nr
static inline int online_section(struct mem_section *section)
{return (section && (section->section_mem_map & SECTION_IS_ONLINE));
}static inline int online_section_nr(unsigned long nr)
{return online_section(__nr_to_section(nr));
}
(1)
online_section该函数接受一个指向 struct mem_section 结构体的指针 section,表示要检查的内存段。struct mem_section 是内核中用于表示物理内存段的数据结构。SECTION_IS_ONLINE 是一个标志位,表示内存段是否在线的标识。
函数的作用是检查给定的内存段是否有效且在线。通过检查 section 是否为非空指针,并且检查 section->section_mem_map 中的 SECTION_IS_ONLINE 标志位,来确定内存段是否在线。如果内存段有效且在线,则返回非零值,否则返回零。
(2)
online_section_nr函数接受一个无符号长整型参数 nr,表示要检查的内存段号。__nr_to_section(nr) 是一个宏定义,用于将内存段号转换为对应的内存段结构体(struct mem_section)指针。
函数的作用是通过调用 online_section 函数,检查给定内存段号对应的内存段是否在线。它将内存段号转换为对应的内存段结构体指针,并将该指针作为参数传递给 online_section 函数进行检查。
参考资料
Linux 4.19.90
相关文章:
Linux 内核内存管理 pfn_to_online_page宏
文章目录 一、Memory Hotplug1.1 简介1.2 热插拔事件通知机制 二、pfn_to_online_page2.1 pfn_to_online_page2.2 pfn_to_section_nr2.3 online_section_nr 参考资料 一、Memory Hotplug 1.1 简介 Linux 内存热插拔(Memory Hotplug)是指在运行时动态增…...
『C语言初阶』第八章 -结构体
前言 今天小羊又来给铁汁们分享关于C语言的结构体,在C语言中,结构体类型属于一种构造类型(其他的构造类型还有:数组类型,联合类型),今天我们主要简单了解一下结构体。 一、结构体是什么&#x…...
chatgpt汇编,两个关于chatgpt的问题
1.用C写一个高级的可自主学习的AI语言模型 编写一个高级的可自主学习的AI语言模型是一个复杂且庞大的工程,需要深入的专业知识和大量的时间精力。下面是一个简化的示例,演示如何使用C实现一个基本的可自主学习的AI语言模型。 首先,你需要定…...
ps丢失d3dcompiler_47.dll怎么办,启动无反应,分享三个解决方法
d3dcompiler_47.dll64位是windows系统中重要的dll文件,缺少了它可能会引起部分软件或者游戏不能运行。 如果系统出现“找不到d3dcompiler_47.dll”或“d3dcompiler_47.dll丢失”等错误信息,那么我们就该着手修复它。 先带了解一下d3dcompiler_47.dll是什…...
第三章nginx详解
nginx:高性能,轻量级的web服务软件。 特点: 1,稳定性高。(没有apache稳定) 2,系统资源消耗地较低。(处理http请求的并发能力非常高,单台物理服务器可以处理30000-5000…...
【二叉树前沿篇】树
【二叉树前沿篇】树 1 树的概念2. 树的相关概念3. 树的表示4. 树在实际中的运用(表示文件系统的目录树结构) 1 树的概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做树是…...
python3 0基础学习----数据结构(基础+练习)
python 0基础学习笔记之数据结构 📚 几种常见数据结构列表 (List)1. 定义2. 实例:3. 列表中常用方法.append(要添加内容) 向列表末尾添加数据.extend(列表) 将可迭代对象逐个添加到列表中.insert(索引,插入内容) 向指定…...
计算机科学中的“旅行商问题”
题目:旅行商问题(Traveling Salesman Problem) 当初为何收藏:我收藏了这个题目是因为它是一个经典而富有挑战性的组合优化问题,涉及到计算机科学、算法设计和实际应用领域。我认为这个问题可以展示出算法设计的重要性…...
QT:自定义控件(Connect使用,子控件连接)
自定义控件封装: 1.添加新文件(设计师界面类),创建子页面 ,放自己想要的控件 2.在主页面中使用子控件 :新建一个widget- ISO21434 组织网络安全管理(二) ISO21434 项目网络安全管理(三) ISO21434 分布式网络安全(四) SO21434 持续进行的网络安全(五) ISO21434 概念阶段网络安全(六)...
Visual Studio 如何放大代码字体的大小
1.打开Visual Studio,新建一个程序,一段代码,为接下去的操作做好准备。单击菜单栏的【工具】选项。 2.在跳出来菜单中找到【选项】(一般在最后一项),然后单击。跳出新的窗口。 3.跳出新的窗口后ÿ…...
Verilog同步FIFO设计
同步FIFO(synchronous)的写时钟和读时钟为同一个时钟,FIFO内部所有逻辑都是同步逻辑,常常用于交互数据缓冲。 异步FIFO:数据写入FIFO的时钟和数据读出FIFO的时钟是异步的(asynchronous) 典型同步FIFO有三部分组成: (1࿰…...
Php“牵手”lazada商品详情页数据采集方法,lazadaAPI接口申请指南
lazada详情接口 API 是开放平台提供的一种 API 接口,它可以帮助开发者获取商品的详细信息,包括商品的标题、描述、图片等信息。在电商平台的开发中,详情接口API是非常常用的 API,因此本文将详细介绍详情接口 API 的使用。 一、la…...
Sentinel 规则持久化
文章目录 Sentinel 规则持久化一、修改order-service服务1.引入依赖2.配置nacos地址 第二步修改非常麻烦,可以略过,直接使用已经打好包的来使用二、修改sentinel-dashboard源码1. 解压2. 修改nacos依赖3. 添加nacos支持4. 修改nacos地址5. 配置nacos数据…...
元宇宙时代超高清视音频技术白皮书关于流媒体协议和媒体传输解读
流媒体协议 元宇宙业务场景对流媒体传输的实时性和互动性提出了更高的要求,这就需要在传统的 RTMP、SRT、 HLS 等基础上增加实时互动的支持。实时互动,指在远程条件下沟通、协作,可随时随地接入、实时地传递虚实融合的多维信息,身…...
【计算机设计大赛】国赛一等奖项目分享——基于多端融合的化工安全生产监管可视化系统
文章目录 一、计算机设计大赛国赛一等奖二、项目背景三、项目简介四、系统架构五、系统功能结构六、项目特色(1)多端融合(2)数据可视化(3)计算机视觉(目标检测) 七、系统界面设计&am…...
深入理解【二叉树】
📙作者简介: 清水加冰,目前大二在读,正在学习C/C、Python、操作系统、数据库等。 📘相关专栏:C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。 欢迎点赞 👍…...
RequestRespons
文章目录 Request&Respons1 Request和Response的概述2 Request对象2.1 Request继承体系2.2 Request获取请求数据2.2.1 获取请求行数据2.2.2 获取请求头数据2.2.3 获取请求体数据2.2.4 获取请求参数的通用方式 2.3 IDEA快速创建Servlet2.4 请求参数中文乱码问题2.4.1 POST请…...
UniApp 使用命令创建页面的详细指南
系列文章目录 文章目录 系列文章目录前言一、安装Uni-CLI二、创建页面三、页面创建命令四、页面结构五、页面使用总结 前言 UniApp是一款跨平台的前端框架,可以用于开发同时运行在多个平台(如微信小程序、H5、App等)的应用程序。本文将详细介…...
Opencv 图像的读取与写入
目录 导入cv2 读取图像数据 创建一个窗口 waitKey方法 关闭所有窗口 完整示例 保存图片 示例 导入cv2 # 导入opencv包 import cv2 读取图像数据 cv2.imread(path, flag) 参数说明: path:要读取的图像文件的路径。 flag(可选&#…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
