3.3 windows,ReactOS系统中页面的换出----1
系列文章目录
文章目录
- 系列文章目录
- 3.3 页面的换出
- MiBalancerThread()
- MmTrimUserMemory()
- MmPageOutVirtualMemory()
3.3 页面的换出
在前一节中我们看到,如果有映射的页面已经被倒换到磁盘上即倒换文件中,那么对这个页面的访问就会引起一次缺页异常,而相应的异常处理程序就会从磁盘上把这个页面倒换进来。这自然就会产生一个问题:这个页面是在什么时候又是怎样跑到磁盘上去的呢?当然,页面(的内容)不会自己跑到磁盘上,而得有个行为主体将其倒出到磁盘上,这个行为主体就是内核线程MiBalancerThread() .
MiBalancerThread()
VOID STDCALL
MiBalancerThread(PVOID Unused)
{PVOID WaitObjects[2];....WaitObjects[0] = &MiBalancerEvent;//通过Event唤醒WaitObjects[1] = &MiBalancerTimer;//通过定时器唤醒while (1){Status = KeWaitForMultipleObjects(2,WaitObjects,WaitAny,Executive,KernelMode,FALSE,NULL,NULL);if (Status == STATUS_SUCCESS){//因为事件而被(某个线程)唤醒/* MiBalancerEvent */CHECKPOINT;while (MmStats.NrFreePages < MiMinimumAvailablePages + 5){//循环,知道有一个数量的空闲物理页面for (i = 0; i < MC_MAXIMUM; i++){if (MiMemoryConsumers[i].Trim != NULL){//调用内存消费者的修剪函数NrFreedPages = 0;Status = MiMemoryConsumers[i].Trim(MiMinimumPagesPerRun, 0, &NrFreedPages);if (!NT_SUCCESS(Status)){KEBUGCHECK(0);}}}}InterlockedExchange(&MiBalancerWork, 0);CHECKPOINT;}else if (Status == STATUS_SUCCESS + 1){/* MiBalancerTimer *///因超时而被唤醒ShouldRun = MmStats.NrFreePages < MiMinimumAvailablePages + 5 ? TRUE : FALSE;for (i = 0; i < MC_MAXIMUM; i++)//对于所有的内存消费者{if (MiMemoryConsumers[i].Trim != NULL){NrPagesUsed = MiMemoryConsumers[i].PagesUsed;if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget || ShouldRun){//本消费者占用页面数已超过配额,或总库存已降到危险点if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget){Target = max (NrPagesUsed - MiMemoryConsumers[i].PagesTarget,MiMinimumPagesPerRun);}else{Target = MiMinimumPagesPerRun;//每次至少修剪的数量}NrFreedPages = 0;//执行本消费者的修剪函数Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);if (!NT_SUCCESS(Status)){KEBUGCHECK(0);}}}}}else{//因其他原因被唤醒,不应发生DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);KEBUGCHECK(0);}}
}
这个线程平时都在睡眠,但是周期性地通过事件MiBalancerTimer 被定时器唤醒。此外,这个线程也可以通过事件 MiBalancerEvent 被唤醒,这发生在需要分配物理页面却发现库存不足的时候每当这个线程被唤醒的时候,它就借助若干个内存“消费者(Consumer)”的“修剪函数”对内存加以“修剪(Trim)”。所谓修剪,就是把一些判断为暂时不会被访问的页面(的内容)倒换出去,腾出所占据的物理页面另行分配,
如前所述,所谓内存“消费者”并不是指实际占用着物理页面的进程,而是指各种不同的用途例如用户空间的页面映射,内核中的可倒换物理页面池、不可倒换物理页面池,磁盘上扇区内容的高速缓存等。内核中有个结构数组MiMemoryConsumers[],其中的每个元素都代表一个“消费者”其下标可以是:
#define MC_CACHE (0)
#define MC_USER (1)
#define MC_PPOOL (2)
#define MC_NPPOOL (3)
#define MC_MAXIMUM (4)
显然,每一种用途即“消费者”都应该提供自己的修剪函数:但是目前ReactOS只为MC_CACHE和MC_USER提供了修剪函数。换言之,另两种用途的页面是不让修剪的。其中用户空间页面所映射物理页面的修剪函数为MmTrimUserMemory()。
MmTrimUserMemory()
[MiBalancerThread()>MmTrimUserMemory()]/* FUNCTIONS *****************************************************************/NTSTATUS
MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
{PFN_TYPE CurrentPage;PFN_TYPE NextPage;NTSTATUS Status;(*NrFreedPages) = 0;CurrentPage = MmGetLRUFirstUserPage();//运用LRU算法找到第一个可以倒出的页面while (CurrentPage != 0 && Target > 0){NextPage = MmGetLRUNextUserPage(CurrentPage);//下一个可以倒出的页面//倒出物理页面 CurrentPageStatus = MmPageOutPhysicalAddress(CurrentPage);if (NT_SUCCESS(Status)){DPRINT("Succeeded\n");Target--;(*NrFreedPages)++;}else if (Status == STATUS_PAGEFILE_QUOTA)//已超过倒换文件的容量配额{MmSetLRULastPage(CurrentPage);//下次再来}CurrentPage = NextPage;}return(STATUS_SUCCESS);
}
参数Target是要求修剪的页面数量,NrFreedPages用来返回实际修剪的数量,另一个参数Priority实际上没有被用到。
修剪的对象是“最近最少被用到”的页面,相应的算法为LRU。与MiMemoryConsumers[]平行,内核中还有个队列头数组 UsedPageListHeads[],也是以 MC_USER 等为下标,凡是被分配用于某个消费者的物理页面,其数据结构都按LRU的次序挂在其队列中。LRU是一种常用的算法,我们就不深入到这里面去了。
找到修剪对象的物理页面号之后,就通过MmPageOutPhysicalAddressO)将其倒换出去。
MmPageOutVirtualMemory()
[MiBalancerThread()> MmTrimUserMemory() > MmPageOutPhysicalAddress()>MmPageOutVirtualMemory()]NTSTATUS
NTAPI
MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,PMEMORY_AREA MemoryArea,PVOID Address,PMM_PAGEOP PageOp)
{PFN_TYPE Page;BOOLEAN WasDirty;SWAPENTRY SwapEntry;NTSTATUS Status;DPRINT("MmPageOutVirtualMemory(Address 0x%.8X) PID %d\n",Address, AddressSpace->Process->UniqueProcessId);/** Check for paging out from a deleted virtual memory area.*/if (MemoryArea->DeleteInProgress){PageOp->Status = STATUS_UNSUCCESSFUL;KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);MmReleasePageOp(PageOp);return(STATUS_UNSUCCESSFUL);}/** Disable the virtual mapping.//关断目标页面的映射*/MmDisableVirtualMapping(AddressSpace->Process, Address,&WasDirty, &Page);if (Page == 0){KEBUGCHECK(0);}/** Paging out non-dirty data is easy.*/if (!WasDirty){//页面是干净的,物理页面空白或其内容与倒换文件中的对应页面完全相同MmLockAddressSpace(AddressSpace);MmDeleteVirtualMapping(AddressSpace->Process, Address, FALSE, NULL, NULL);MmDeleteAllRmaps(Page, NULL, NULL);if ((SwapEntry = MmGetSavedSwapEntryPage(Page)) != 0){MmCreatePageFileMapping(AddressSpace->Process, Address, SwapEntry);MmSetSavedSwapEntryPage(Page, 0);}MmUnlockAddressSpace(AddressSpace);MmReleasePageMemoryConsumer(MC_USER, Page);PageOp->Status = STATUS_SUCCESS;KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);MmReleasePageOp(PageOp);return(STATUS_SUCCESS);}/** If necessary, allocate an entry in the paging file for this page*/SwapEntry = MmGetSavedSwapEntryPage(Page);if (SwapEntry == 0){SwapEntry = MmAllocSwapPage();if (SwapEntry == 0){MmShowOutOfSpaceMessagePagingFile();MmEnableVirtualMapping(AddressSpace->Process, Address);PageOp->Status = STATUS_UNSUCCESSFUL;KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);MmReleasePageOp(PageOp);return(STATUS_PAGEFILE_QUOTA);}}/** Write the page to the pagefile*/Status = MmWriteToSwapPage(SwapEntry, Page);if (!NT_SUCCESS(Status)){DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",Status);MmEnableVirtualMapping(AddressSpace->Process, Address);PageOp->Status = STATUS_UNSUCCESSFUL;KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);MmReleasePageOp(PageOp);return(STATUS_UNSUCCESSFUL);}/** Otherwise we have succeeded, free the page*/DPRINT("MM: Swapped out virtual memory page 0x%.8X!\n", Page << PAGE_SHIFT);MmLockAddressSpace(AddressSpace);MmDeleteVirtualMapping(AddressSpace->Process, Address, FALSE, NULL, NULL);MmCreatePageFileMapping(AddressSpace->Process, Address, SwapEntry);MmUnlockAddressSpace(AddressSpace);MmDeleteAllRmaps(Page, NULL, NULL);MmSetSavedSwapEntryPage(Page, 0);MmReleasePageMemoryConsumer(MC_USER, Page);PageOp->Status = STATUS_SUCCESS;KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);MmReleasePageOp(PageOp);return(STATUS_SUCCESS);
}
需要倒换出去的页面可能是“干净”的,也可能是“脏”的。
所谓干净的页面,是指自从上一次建立通向这个物理页面的映射以来从未对其进行过写操作的面,具体有两种可能:
1,这是个刚被分配并建立映射但从未被写过的空白页面。这样的页面在倒换文件中尚无对应的倒换页面,也不需要有,因为以后需要时可以重新分配一个空白页面。所以只要删除其映射,并通过 MmDeleteAlRmaps()使其与所属的进程脱钩,最后释放这个物理页面就可以了
2,这是个从倒换文件换入的页面,但是换入之后从未被写过。这样的页面在倒换文件中已经有了对应的倒换页面,但是不需要改变倒换页面的内容。对于这样的页面,一方面要删除其映射,另一方面要使相应的页面映射表项指向倒换文件中的页面。凡是有了倒换页面的物理页面,其PHYSICAL PAGE结构中的SavedSwapEntry字段就指向这个倒换页面,现在一方面将该字段的内容转移到相应的页面映射表项中(并将其PAPRESENT标志位清0),另一方面通过 MmSetSavedSwapEntryPage()将这个字段清 0。然后再释放这个物理页面。
倒换页面是由“倒换页面项”SWAPENTRY描述的,这是个32位无符号整数,实际上是倒换文件号与文件内页面号的组合
所谓脏的页面,则是指自从上一次建立通向这个物理页面的映射以来已经对其进行过写操作的面,具体又有两种可能:
1,这本是个刚被分配并建立映射的空白页面,但是现在已经不再空白。这样的页面在倒换文件中尚无对应的倒换页面,但是需要有。所以通过MmAllocSwapPageO)分配一个倒换页面这个函数返回一个SWAPENTRY,说明是哪一个倒换文件中的哪一个页面。然后通过MmWriteToSwapPage()将页面的内容写入倒换文件,再将相应的页面映射表项改成指向倒换页面(并将其 PA_PRESENT标志位清0),最后释放该物理页面。
2,这是个从倒换文件换入的页面,但是换入之后已经被写过。这样的页面在倒换文件中已经有了对应的倒换页面,但需要改变其内容。所以也由MmWriteToSwapPageO)将页面的内容写入倒换文件,再将相应的页面映射表项改成指向倒换页面(并将其PA_PRESENT标志位清 0),最后释放该物理页面。
至于 MmWriteToSwapPage(),则已经属于文件操作的范畴,这里就不深入下去了。最后再概括一下倒换页面与物理内存页
面和页面映射表项PTE之间的关系:
1,如果(虚存)页面的内容在物理页面中,则相应的PTE指向该物理内存页面,而物理内存页面的 PHYSICAL_PAGE结构中的SavedSwapEntry 字段指向作为后备的倒换页面。
2,如果(虚存)页面的内容不在物理页面中,则相应的PTE直接指向倒换页面。
相关文章:
3.3 windows,ReactOS系统中页面的换出----1
系列文章目录 文章目录 系列文章目录3.3 页面的换出MiBalancerThread()MmTrimUserMemory()MmPageOutVirtualMemory() 3.3 页面的换出 在前一节中我们看到,如果有映射的页面已经被倒换到磁盘上即倒换文件中,…...
QCustomPlot添加自定义的图例,实现隐藏、删除功能(二)
文章目录 实现步骤:详细代码示例:实现原理和解释:使用方法:其他参考要实现一个支持复选框来控制曲线显示和隐藏的自定义 QCPLegend 类,可以通过继承 QCPLegend 并重写绘制和事件处理方法来实现,同时发出信号通知曲线的状态变更。 实现步骤: 继承 QCPLegend 类,添加绘…...

Linux云计算 |【第五阶段】CLOUD-DAY8
主要内容: 掌握DaemonSet控制器、污点策略(NoSchedule、Noexecute)、Job / CronJob资源对象、掌握Service服务、服务名解析CluterIP(服务名自动发现)、(Nodeport、Headless)、Ingress控制器 一…...

岛屿数量 广搜版BFS C#
和之前的卡码网深搜版是一道题 力扣第200题 99. 岛屿数量 题目描述 给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。…...
hive切换表底层文件类型以及分隔符
1、改底层文件存储类型,但是一般只会在数据文件与期望类型一致的时候使用,比如load等方式时发现建表时没指定对这样的,因为这个语句不会更改具体的底层文件内容,只改元数据 ALTER TABLE 表名 SET FILEFORMAT 希望类型;2、更改数据…...
ChatGPT o1与GPT-4o、Claude 3.5 Sonnet和Gemini 1.5 Pro的比较
全新的ChatGPT o1模型(代号“Strawberry”)是OpenAI的最新进展,专注于以前的AI模型难以应对的领域:高层次推理、数学和复杂编程。OpenAI设计o1模型以花费更多时间思考问题,使其在需要逐层推理的任务中提高准确性。本文…...

asp.net文件防盗链
URLRewriter实现 可以参考下面的文章 代码 .net framework 新建asp.net framework的web项目,新建AntiTheftChainHandler using System.Web;namespace AntiTheftChainStu01.Handler {public class AntiTheftChainHandler : IHttpHandler{public bool IsReusable…...

【日志】力扣58.最后一个单词的长度//14.最长公共前缀//28. 找出字符串中第一个匹配项的下标
2024.11.6 【力扣刷题】 58. 最后一个单词的长度 - 力扣(LeetCode)https://leetcode.cn/problems/length-of-last-word/?envTypestudy-plan-v2&envIdtop-interview-150 int lengthOfLastWord(char* s) {int count 0;for (int i strlen(s) - 1; i…...
华为杯”第十五届中国研究生数学建模竞赛-B题:光传送网建模与价值评估(续)
目录 4. 问题二 光传送网规划 4.1 基本假设 4.2 模型建立 4.3 子问题一 4.2 子问题二 4.5 子问题三 5. 问题三 改善星座图 5.1 问题简述 5.2 问题分析 5.3 建模与问题求解 5.3.1 方案一 5.3.2 方案二 6. 模型评价 6.1 模型的优点 6.2 模型的缺点 参考文献 本文篇幅较长,分为上…...
android 使用xml设置背景图片和圆角
使用xml设置背景图片和圆角 <?xml version"1.0" encoding"utf-8"?> <layer-list xmlns:android"http://schemas.android.com/apk/res/android"><item><shape><solid android:color"android:color/transparen…...
数据结构,问题 E: 表达式括号匹配
题目描述 假设一个表达式有英文字母(小写)和数字、运算符(,—,*,/)和左右小(圆)括号构成,以“”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号…...

国家宠物美容师职业技能等级评价(高级)理论考试题
国家宠物美容师职业技能等级评价 理论考试复习参考范围 高级/三级 宠物美容师(高级)理论考试题 一 判断题 犬只的世界只有黑白灰三种,通过颜色呈现的深浅度进行辨识(A ) A 对 B 错 美国养犬俱乐部简称AKC…...

Spring挖掘:(AOP篇)
学习AOP时,我们首先来了解一下何为AOP 一. 概念 AOP(面向切面编程,Aspect Oriented Programming)是一种编程技术,旨在通过预编译方式或运行期动态代理实现程序功能的统一管理和增强。AOP的主要目标是在不改变原有业务逻辑代码的…...
十四届蓝桥杯STEMA考试Python真题试卷第二套第四题
来源:十四届蓝桥杯STEMA考试Python真题试卷第二套编程第四题:糖果罐调整 该题解通过贪心策略在每一步都选择对当前状态最有利的操作,从而达到最少调整次数的目标。 题目描述 现有 N 罐糖果,且已知每罐糖果的初始数量。现给出两个数值 L 和 R(L≤R),需要把每罐糖果的数…...
单元测试怎么做
单元测试是软件开发中非常重要的一部分,能够确保代码的正确性、可靠性和可维护性。对于 Vue 项目来说,单元测试主要关注的是测试组件及其相关功能是否正常。下面是如何在 Vue 项目中进行单元测试的详细步骤,包括测试框架的选择、测试工具的配…...

移动应用开发 实验二:标准身高计算器
文章目录 准备工作一,创建Android Studio项目二,创建活动模块三,设计用户界面(一)设置页面布局(二)添加标题文本控件(三)设计体重输入框(四)设计性…...

金华迪加现场大屏互动系统 mobile.do.php 任意文件上传漏洞复现
0x01 产品描述: 金华迪加现场大屏互动系统是由金华迪加网络科技有限公司开发的一款专注于增强活动现场互动性的系统。该系统设计用于提供高质量的现场互动体验,支持各种大型活动,如企业年会、产品发布会、展览展示等。其主要功能包…...
使用 pd.ExcelWriter 创建多工作表 Excel 文件的详细教程
with pd.ExcelWriter(...) as writer 可以将多个内容写入一个 Excel 文件中。具体地说,它创建了一个Excel 文件写入器,使得我们可以在一个文件中创建多个工作表(Sheet)。 with pd.ExcelWriter("模型指标和损失值.xlsx")…...

驱动-----dht11温湿度传感器
单总线:只用一根线。 复位信号:设置为输出模式,低电平20ms,然后再拉高30us。然后设置为输入模式,dht11会先拉低80us,然后拉高80us表示对接成功 数据0:开始先拉低50us,然后拉高26~28u…...
Docker 基础命令简介
目录 Docker 基础命令 1. Docker 版本信息 2. 获取 Docker 帮助 3. 列出所有运行中的容器 4. 运行一个新的容器 5. 查看容器日志 6. 停止容器 7. 启动已停止的容器 8. 删除容器 9. 列出所有镜像 10. 拉取镜像 11. 构建镜像 12. 删除镜像 13. 执行命令 14. 查看容…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...
高防服务器价格高原因分析
高防服务器的价格较高,主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因: 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器,因此…...