解析Windows 2000/XP进程工作集

2023-05-16

 在《解析Windows  2000/XP物理内存管理》中我详细的介绍了页框数据库(Page Frame Database)的概念,提到在物理内存的组织与管理方面对于每个页面系统都在页框数据库中保存一个结构,用于跟踪页面状态等。但页框数据库并不能真正协调物理内存的使用。我们知道,Windows 是一个多任务的操作系统,而物理内存却是一个相对贫乏的资源,为避免某个进程(或是系统)耗尽这一资源,引入了工作集(WorkingSet)的概念。WorkingSet是内存管理一个相当重要的术语,在Windows  2000/XP 中通常分为两种即进程工作集与系统工作集,分别用于跟踪各个进程与系统的物理内存使用情况。由于终端服务的引入,另有一种工作集会话(Session)工 作集,用于跟踪各个Session使用物理内存的情况。本文从进程工作集的内部组织方式出发,简要阐述工作集在Windows  2000/XP中的组织与管理。

    EPROCESS 是描述进程的结构,所以从EPROCESS入手,肯定也能找到进程工作集的表示方式。实际上位于EPROCESS中的子结构MMSUPPORT就是关于进 程与内存子系统相关的一些关键内容,进程工作集自然也在此。对于早期的内核版本这些内容没有集成至MMSUPPORT结构中,而且各版本间 MMSUPPORT的定义是不相同的,底下列出MMSUPPORT在Windows  XP Build 2600 SP0中的定义(本文中所有结构都可能只适用于这一版本):

    typedef struct _MMSUPPORT {
        LARGE_INTEGER   LastTrimTime;
        MMSUPPORT_FLAGS Flags;
        ULONG           PageFaultCount;
        ULONG           PeakWorkingSetSize;
        ULONG           WorkingSetSize;
        ULONG           MinimumWorkingSetSize;
        ULONG           MaximumWorkingSetSize;
        PMMWSL          VmWorkingSetList;
        LIST_ENTRY      WorkingSetExpansionLinks;
        ULONG           Claim;
        ULONG           NextEstimationSlot;
        ULONG           NextAgingSlot;
        ULONG           EstimatedAvailable;
        ULONG           GrowthSinceLastEstimate;
    } MMSUPPORT, *PMMSUPPORT;

    MMSUPPORT 中PeakWorkingSetSize、WorkingSetSize、MinimumWorkingSetSize与 MaximumWorkingSetSize分别表示此进程的工作集峰值、当然工作集大小、允许工作集的最大值与最小值。性能监视器 (perfmon.msc)与任务管理器(taskmgr.exe)都可对这些数据进程跟踪显示。 Win32 API GetProcessWorkingSetSize(Ex)和SetProcessWorkingSetSize(Ex)在具有相应 PROCESS_QUERY_INFORMATION与PROCESS_SET_QUOTA权限后即能获取或设置 MinimumWorkingSetSize与MaximumWorkingSetSize等。

    进程在建立时,进程工作集总为空 的,CreateProcess等在建立进程过程中有责任初始化进程工作集。它会分配一个物理页面,然后调用 MiInitializeWorkingSetList初始化进程工作集。后者以刚建立的EPROCESS作为参数初始化我们上面提到的 MMSUPPORT结构。这里要提到一个很重要的成员VmWorkingSetList(结构MMWSL),定义如下:

   +0x000 Quota            : Uint4B
   +0x004 FirstFree        : Uint4B
   +0x008 FirstDynamic     : Uint4B
   +0x00c LastEntry        : Uint4B
   +0x010 NextSlot         : Uint4B
   +0x014 Wsle             : Ptr32 _MMWSLE
   +0x018 LastInitializedWsle : Uint4B
   +0x01c NonDirectCount   : Uint4B
   +0x020 HashTable        : Ptr32 _MMWSLE_HASH
   +0x024 HashTableSize    : Uint4B
   +0x028 NumberOfCommittedPageTables : Uint4B
   +0x02c HashTableStart   : Ptr32 Void
   +0x030 HighestPermittedHashAddress : Ptr32 Void
   +0x034 NumberOfImageWaiters : Uint4B
   +0x038 VadBitMapHint    : Uint4B
   +0x03c UsedPageTableEntries : [768] Uint2B
   +0x63c CommittedPageTables : [24] Uint4B

    效率上考虑,Windows  2000/XP 均将这一结构映射至一固定的虚拟内存地址中。由内核变量MmWorkingSetList指定,实际上 MiInitializeWorkingSetList就是直接引用这个变量对MMSUPPORT结构的VmWorkingSetList成员进行操作 的。MmWorkingSetList位于内核区域(在Windows  XP Build 2600 Professional 中为0xc0503000),通常内核区域均是由所有进程共享的,但显然MmWorkingSetList指定的WorkingSet情况对于每个进程都 有不同的映射,即具有不同的内容,这与进程页目录或是页表一样。后者我在《小议Windows  NT/2000分页机制》中详细的做过测试。

    因 为进程WorkingSet是用于描述进程使用物理内存的情况,换句话说位于WorkingSet中的页面均位于物理内存中(没有被置换到 pagefile.sys中等),所以访问这些页面均不会导致Page Fault。我们可以使用VirtualLock将页面置入进程工作集中。反过来 想,系统如何知道某一页面(使用虚拟页面地址),针对这一进程是否存在于工作集中呢?粗粗浏览一下上面给出的MMWSL的定义,就知道Windows  2000/XP使用哈希表(HashTable)来组织这些页面。HashTable具有快速检索的特点,正好适合于WorkingSet频繁访问的特点。另一个例子是系统全局命名内核的组织,详见《剖析Windows  NT/2000内核对象组织》。与Windbg提供dump全局命令内核对象的!object命令一样,Windbg提供!wsle用于dump进程工作集。例如:

    kd> !wsle 7

    Working Set @ c0503000
        FirstFree:      469  FirstDynamic:          7
        LastEntry      46c  NextSlot:         4  LastInitialized      658
        NonDirect      145  HashTable: c06f4000  HashTableSize:       400

    Reading the WSLE data...
    ..
    Virtual Address      Age    Locked  ReferenceCount
        c0300203          0        1        1
        c0301203          0        1        1
        c0502203          0        1        1
        c0503203          0        1        1
        c0504203          0        1        1
        c06f4203          0        1        1
        c06f5203          0        1        1
        c0505203          0        1        1
        c0506203          0        1        1
        77c47029          0        0        1
                              .
                              .
                              .

    wsle 命令只是将VmWorkingSetList的Wsle成员(MMWSLE指针)指向的数组的每个元素dump出(每个元素32bit)。windbg 的!wsle命令获得的结果中Virtual Address列即Wsle的每一个32bit的内容。如下windbg命令所示:

    kd> dd MmWorkingSetList l 1   //当前进程MMWSL结构所在的地址,如本文前头描述。
    805467d0  c0503000
    kd> dd c0503000 l 10          //MMWSL内容
    c0503000  000003b9 000003ba 00000007 000003b9
    c0503010  00000004 c050369c 00000658 0000014c
                       --------
                           |_MMWSLE内容(如上给出的MMWSL定义,MMWSLE是一个指针)

    c0503020  c06f4000 00000400 0000001a c06f4000
                 |         |_HashTableSize(Uint4B)哈希表大小
                 |_HashTable(MMWSLE_HASH)地址(底下将会用到这两个数值)
    c0503030  c0800000 00000000 0000005c 004d023a



    kd> dd c050369c  
    //结果即上面wsle命令输出的Virtual Address列(WorkingSet
    //频繁变动,如果有稍许不同可能是系统已经更改过了)。
    c050369c  c0300203 c0301203 c0502203 c0503203
    c05036ac  c0504203 c06f4203 c06f5203 c0505203

    实际上这里的每一个Virtual Address,就像上所示的如c0300203不仅仅是Virtual Address,因为WorkingSet是以页面为单位的,所以这些32bit的内容中有12bit用于其它用途。实际上在Windows  XP中这个32bit的内容定义为MMWSLENTRY,具体为:

    Valid            : Pos 0, 1 Bit
    LockedInWs       : Pos 1, 1 Bit
    LockedInMemory   : Pos 2, 1 Bit
    Protection       : Pos 3, 5 Bits
    SameProtectAsProto : Pos 8, 1 Bit
    Direct           : Pos 9, 1 Bit
    Age              : Pos 10, 2 Bits
    VirtualPageNumber : Pos 12, 20 Bits

    wsle命令也即根据这低12bit输出WSLE的一些属性:如Age与Locked。ReferenceCount则位于PFN中,具体请参阅《解析Windows  2000/XP物理内存管理》。

    整 个结构至此已经比较明朗了,但是正像上面提到的WorkingSet访问是非常频繁的,在检索指定虚拟地址的页面是否在WorkingSet中还要依靠另 一个重要的成员HashTable。既然通过HashTable,我们来给出HashFunction(有兴趣想知道如何得到HashFunction的 可像我一样看看MiInsertWsle是如何实现的)。

    ((PVA >>a) & 0x3ffffc) % (HashTableSize-1)

    这 里,PVA指页面虚拟地址,而HashTableSize指当前进程的WorkingSet哈希表的大小。对于给定的一个页面,如何在WSLE数组中快速 的检索到这个页面的数组下标呢?有了哈希表,当然通过Hash表了。这样描述还是比较抽象,我们以一个具体的例子说明问题:从上面wsle命令输出结果, 我们知道虚拟地址77c47000(77c47029那一行),未于MMWSLE的第十项(数组下标为9,即index为9),而这个进程的工作集 HashTableSize值为0x400(这个值可能系统会在需要时通常MiGrowWsleHash更改),所以:

    ((77c47029>>a)&0x3ffffc) % (0x400-1)

    值 为0x9a,所以位于HashTable的第0x9a个Bucket中(以0开始),通过上面得到的HashTable地址c06f4000,找到第 0x9a个bucket。而每个Bucket的大小呢?需要说明的是这个HashTable的每个Bucket如下定义(_MMWSLE_HASH):

    +0x000 Key              : Uint4B
    +0x004 Index            : Uint4B

    即每个bucket为8个字节,所以我们用如下kd命令得到结果:

    kd> dd c06f4000+9a*8 l 2
    c06f44d0  77c47000 00000009

    其Key值为77c47000,即虚拟地址,Index值为9,即验证了上面windbg的wsle命令输出结果。现在,对于WorkingSet的组织也已经讨论的差不多了,需要指出的是在Windows  XP 中WorkingSet的设计远比这讨论的多很多内容,比如WorkingSet的哈希表是可扩展的(通过 MiGrowWsleHash),HashTable内容的插入、更改、删除,还有工作集修整(通过MiTrimWorkingSet)等等,特别是工作 集修整,文章开头提到工作集的一个主要作用合理利用物理内存,避免某个进程(或是系统)耗尽物理内存,通过WorkingSet的最大、最小值与 Quota指定的限额,限定物理内存的使用。如果出现越出这样的一个范围或是物理内存耗尽,则会使用工作集修整。Andrew Tanenbaum的 《Modern Operating Systems》介绍了多种工作集修整的算法,在单处理器中Windows  2000/XP中使用了更像LRU的时候算法(Clock algorithm正像很多Unix系统实现一样),你应该看到上面输出的Age的值吧。由于条件限制我只能在单处理器上实验过。为了篇幅完整,我简要介绍一下多处理器的情况:多处理中Windows  2000使用FIFO(First In First Out)算法,但从我看到的Microsoft的一些介绍中,似乎Windows  XP/.Net Server 2003在多处理中也使用LRU了,看来Windows 的内核是越来越完善了。

    本 文只介绍了进程工作集,对于系统工作集及Session工作集,大同小异,实际上我是在分析了三种工作集后,才开始着手写这样的一篇。这一些些的概念、结 构在自己的学习过程中不断被发现,也着实让自己兴奋不已,但我从来没有看过任何关于这些结构层次上的讨论,错误之处,在所难免,敬请见谅,谢谢!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解析Windows 2000/XP进程工作集 的相关文章

  • 关闭表单而不退出应用程序

    我目前正在开发一个小项目 希望得到一些帮助 我有两个表单 第一个是登录窗口 第二个是主程序 我遇到的问题是当我关闭时form1 with this Close 它正在退出整个程序 我有一种感觉 我需要使用线程或类似的东西 但我找不到合适的资
  • Windows 控制台支持 ANSI 吗?

    Windows 控制台支持 ANSI 控制字符吗 默认情况下它不支持许多 ANSI 控制字符 维基百科文章中也提到了这一点 http en wikipedia org wiki ANSI escape code http en wikipe
  • 如何使用 WinAPI 读取 MessageBox 文本

    如何读取标准Win消息框 Info 的消息 Using SendMessage this HandleControl WM GETTEXT builder Capacity builder 我只能读取消息框的标题或按钮的文本 但不能读取消息
  • 微软怎么能说WinAPI中一个字的大小是16位呢?

    我刚刚开始学习WinAPI 在MSDN中 对WORD数据类型提供了以下解释 WORD16 位无符号整数 范围是十进制 0 到 65535 该类型在 WinDef h 中声明如下 typedef 无符号短 WORD 很简单 而且它与我一直在使
  • 如何将 .bat 文件中的变量获取到 PowerShell 脚本中?

    我正在用 PowerShell 替换 bat 脚本的部分内容 批处理文件的配置是通过以下文件完成的set适当的环境变量 我正在寻找一种方法将这些变量值加载到 ps1脚本 无需修改 bat文件 因为它们也在其他地方使用 一个例子 bat看起来
  • 有什么工具可以了解 Windows 中正在运行的进程的布局(段)?

    我一直很好奇 该进程在内存中到底是什么样子的 其中有哪些不同的部分 部分 程序 在磁盘上 和进程 在内存中 到底是如何相关的 我之前的问题 有关可执行程序 进程 的内存布局的更多信息 https stackoverflow com ques
  • 该进程无法访问该文件,因为该文件正在被另一个进程使用

    当我从 bat 文件启动 net 控制台应用程序时 例如start myapp exe 然后 myapp exe 尝试将文件写入其当前目录 尽管我收到 net 运行时错误 声称该文件正在被另一个应用程序使用 没有其他应用程序在运行 http
  • 如何仅回显“开”或“关”文本?

    大家都知道 在 Windows 命令文件中 cmd echo on echo off 启用和禁用回显 但是如何仅回显文本 on 或文本 off IE 如何发送文本 on off to stdout 目标系统 Windows XP 那么在 D
  • NSIS获取参数

    to get n 0值作为字符串 不需要选项 传递给安装程序 我不太明白这个函数的工作原理是什么 GetParameters input none output top of stack replaces with e g whatever
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • 使用 GDI+ 和 C++ 减少闪烁

    我在 C MFC 应用程序中使用 GDI 每当调整窗口大小时 我似乎都无法避免闪烁 我已经尝试过以下步骤 返回 TRUEOnEraseBkGnd 返回 NULLOnCtlColor 根据此代码使用双缓冲 void vwView OnDraw
  • 使用 CLion 进行 OpenCV Windows 设置

    我想在 Windows 上为 CLion IDE 设置 OpenCV 我尝试使用 OpenCV 3 1 和 2 4 得到相同的结果 我有 Windows 10 64 位 CLion 使用 cygwin 环境 到目前为止我做了什么 1 从Op
  • WIX 工具集 - 自定义操作命令无法正确检测 Windows 10 版本

    我有一个安装程序 可以部署并运行单独的 exe文件以将驱动程序部署到系统 不幸的是 微软似乎已经放弃了对VersionNTWindows 10 及更高版本中的宏 所以我实施了另一篇文章中建议的方法 https stackoverflow c
  • 当前有哪些 USB 设备(友好名称)连接到 PC?

    我可以获得当前连接到计算机的设备列表吗 我检查了this https stackoverflow com q 3331043 75500 and this https stackoverflow com questions 3685615
  • 通过 Wi-Fi 的 ADB 在一台 PC 上非常慢,但在另一台 PC 上则非常慢

    我正在尝试学习如何为 Android 进行开发 并且我希望能够在我的设备而不是模拟器上进行测试 我手机上的 USB 端口变得非常松动 我不想在使用它进行测试的数十个小时中弄乱它 我在桌面上通过 Wi Fi 启用了 ADB 它运行得非常完美
  • 如何使用批处理文件将多个命令插入到批处理文件中

    我正在制作一个批处理文件 我们称之为 Create bat 它将创建一个批处理文件 我们称之为 Created bat 该文件将在其中插入多个命令 其中一条命令如下 FOR F x IN tasklist NH FI IMAGENAME e
  • 谁能推荐适用于 Windows 的磁盘 I/O 基准测试软件?

    我想测试文件系统在不同条件下的性能 具体来说 我想在 普通硬盘 和 USB 磁盘上测试未压缩和压缩的 Windows 虚拟机的性能 因为确切了解差异是什么会很有趣 我需要的是一个可以测试文件系统不同方面的程序 随机访问 顺序读 写等 并制作
  • 如何使用 Java 以独立于平台的方式读取 Windows 共享驱动器?

    如何使用 Java 从 Windows 共享驱动器中读取数据 以便执行读取的 Java 代码可以在任何平台上同样正确地运行 您可以使用JCIFS http jcifs samba org 使用纯 Java 代码访问 SMB CIFS 共享
  • os.path.expanduser("~") 的替代方案?

    在Python 2 7 x中 os path expanduser Unicode 已损坏 这意味着如果 的扩展中包含非 ASCII 字符 则会出现异常 http bugs python org issue13207 http bugs p
  • Anaconda (Python) - Windows 10 上的 Cmder 集成

    我在 Windows 10 64 位上通过 Anaconda 让 Cmder 使用 Python 时遇到了一些麻烦 我让 Anaconda 工作得很好 测试过用 matplotlib 绘制一些东西 它与 Anaconda Prompt 一起

随机推荐

  • linux swap 内存交换分区 详细介绍

    目录 1 什么是SWAP xff0c 到底是干嘛的 xff1f 为什么要进行内存回收 xff1f 会回收的两种内存 2 swappiness到底是用来调节什么的 xff1f 那么这个swappiness到底起到了什么作用呢 xff1f 3
  • [ 云计算 华为云 ] 华为云开天 aPaaS:构建高效的企业数字化平台(上)

    文章目录 前言一 什么是 aPaaS1 1 初识 aPaaS 二 华为云开天 aPaaS2 1 华为云服务类型与种类2 1 1 基础 aPaaS2 1 2 行业 aPaaS xff08 一 xff09 工业 aPaaS xff08 二 xf
  • linux shell mkpasswd 生成随机密码

    centos 安装命令 xff1a yum install y expect 参数 xff1a l 密码的长度定义 默认是 9 d 数字个数 默认是 2 c 小写字符个数 默认是 2 C 大写字符个数 默认是 2 s 特殊字符个数 默认是
  • ERROR: glib-2.22 gthread-2.0 is required to compile QEMU

    问题描述 xff1a centos 6 5 源码编译qemu configure时出现错误 ERROR glib 2 22 gthread 2 0 is required to compile QEMU 解决方法 xff1a yum ins
  • metasploit msfconsole 命令参数

    在MSF里面msfconsole可以说是最流行的一个接口程序 很多人一开始碰到msfconsole的时候就害怕了 那么多复杂的命令语句需要学习 xff0c 但是msfconsole真的是一个强大的接口程序 Msfconsole提供了一个一体
  • 记事本输入“联通”俩字,关闭再打开乱码

    这是个很有意思的事情 这里需要提一下ANSI xff0c 不同的国家和地区制定了不同的标准 xff0c 由此产生了 GB2312 BIG5 JIS 等各自的编码标准 然后 xff0c 这些编码方式没有固定的格式 xff0c 但是比如说UTF
  • RoboRTS建图

    建图仿真 span class token function cd span RoboRTS ws src span class token function source span devel setup bash roslaunch r
  • RISC和CISC的区别

    文章目录 复杂指令集计算机 CISC 精简指令集计算机 RISC CISC与RISC的区别参考文章 RISC 精简指令集计算机 和CISC 复杂指令集计算机 是当前CPU的两种架构 它们的区别在于不同的CPU设计理念和方法 复杂指令集计算机
  • 单链表逆序(C语言)

    最近在复习数据结构 xff0c 刷题正好遇上 xff0c 所以整理一下 span class token macro property span class token directive keyword include span span
  • 各种颜色RGB值

    各种颜色RGB值 RGB 255 192 203 pink xff08 粉红 xff09 RGB 220 20 60 crimson xff08 腥红 xff09 RGB 255 240 245 lavenderblush xff08 苍白
  • 第一范式、第二范式、第三范式、BCNF范式详解

    文章目录 0 范式 NF 1 第一范式 xff08 1NF xff09 2 第二范式 xff08 2NF xff09 2 1 函数依赖2 1 1完全函数依赖2 1 2 部分函数依赖2 1 3 传递函数依赖 2 2 码2 3 非主属性 3 第
  • 数据库实体关系图(ERD)及其画法

    文章目录 1 什么是ER图 2 什么时候画ER图 2 1 数据库设计2 2 数据库调试2 3 数据库创建和补丁2 4 帮助收集需求 3 ERD符号指南4 概念 逻辑和物理数据模型5 如何绘制ER图 数据库绝对是软件系统不可分割的一部分 在数
  • Threads(异步和多线程)

    Task是 NET Framework3 0出现的 xff0c 线程是基于线程池的 xff0c 然后提供丰富的api xff0c Thread方法很多很强大 xff0c 但是太过强大 xff0c 没有限制 DoSomethingLong方法
  • Linux系统中添加库文件路径的方法

    文章目录 方法一方法二 库文件在链接 xff08 静态库和共享库 xff09 和运行 xff08 仅限于使用共享库的程序 xff09 时被使用 xff0c 其搜索路径是在系统中进行设置的 一般 Linux 系统把 lib和 usr lib
  • Linux 环境下 Qt 可执行程序依赖库打包脚本

    文章目录 一 利用 96 ldd 96 命令查看程序需要的依赖库二 编写依赖库打包脚本三 编写执行文件脚本四 总结 Linux 环境下 Qt 可执行程序依赖库打包脚本 使用 Qt Creator 完成程序编码之后 xff0c 虽然会在 De
  • RSA/ECDSA host key has changed 错误

    RSA host key for mysharebook cn has changed and you have requested strict checking Host key verification failed 这是Linux重
  • VS2013+Python在图像处理中的应用

    对Python的学习要从视频编码说起 其实 xff0c 我一直在用ffmpeg对视频做设计 处理 xff0c 后来发现Opencv也能干同样的事情 xff0c 就想研究一下Opencv是怎么实现的 xff0c 再后来就和Python扯上关系
  • 结构化数据、半结构化数据和非结构化数据

    本文转自http blog csdn net u010069220 article details 46895169 在实际应用中 xff0c 我们会遇到各式各样的数据库如nosql非关系数据库 xff08 memcached xff0c
  • linux中与文件系统相关的命令

    文章目录 前言一 软链接与硬链接二 磁盘与目录容量2 1 df2 1 1 功能2 1 2 范例 2 2 du2 2 1 功能2 2 2 范例 三 磁盘分区 格式化与挂载3 1 分区3 2 格式化3 3 挂载 四 文件及目录的相关操作4 1
  • 解析Windows 2000/XP进程工作集

    在 解析Windows 2000 XP物理内存管理 中我详细的介绍了页框数据库 Page Frame Database 的概念 xff0c 提到在物理内存的组织与管理方面对于每个页面系统都在页框数据库中保存一个结构 xff0c 用于跟踪页面