实验四、内存监视(windows)

问题描述

Windows设计一个内存监视器,要求:
实时地显示当前系统中内存的使用情况,包括系统地址空间的布局,物理内存的使用情况;
实时显示实验二进程控制(ParentProcess.exe)的虚拟地址空间布局和工作集信息
相关的系统调用:
GetSystemInfo, VirtualQueryEx,VirtualAlloc, GetPerformanceInfo, GlobalMemoryStatusEx …

相关知识

GlobalMemoryStatusEx()获取系统内存信息

  1. 获取系统内存信息有2个api,分别是GlobalMemoryStatus和GlobalMemoryStatusEx。GlobalMemoryStatus函数可以在C语言里直接调用,但是GlobalMemoryStatusEx却不可以直接调用。
  2. 看看这2个函数的不同,总的来说这2个函数都可以获取到内存信息,但是GlobalMemoryStatusEx函数是GlobalMemoryStatus函数的增强,GlobalMemoryStatus虽然可以获取,但当你的机器里装了2条内存条是,它只能获取到一条的内存信息容量,而GlobalMemoryStatusEx函数却可以获取到所有,只要你系统识别的内存大小。
BOOL WINAPI  GlobalMemoryStatusEx(MEMORYSTATUSEX  lpBuffer)
//获得当前内存状态的信息

参数:指向一个MEMORYSTATUSEX结构的指针

其中MEMORYSTATUSEX结构如下:

typedef struct _MEMORYSTATUSEX
{
  DWORD     dwLength; //本结构长度
  DWORD     dwMemoryLoad; //已用内存百分比
  DWORDLONG    ullTotalPhys; //物理内存总量
  DWORDLONG    ullAvailPhys; //可用物理内存
  DWORDLONG    ullTotalPageFile; //页交换文件最多能放的字节数
  DWORDLONG    ullAvailPageFile; //页交换文件中尚未分配给进程的字节数
  DWORDLONG    ullTotalVirtual; //用户区总的虚拟地址空间
  DWORDLONG    ullAvailVirtual; //用户区当前可用的虚拟地址空间
//ullAvailVirtual这个值是这个结构中唯一一个与该进程有关的成员,所有的其他成员
//都适用于整个系统,为了计算这个值GlobalMemoryStatus会把调用进程的地址空间中所有的闲置区域都加起来
  DWORDLONG    ullAvailExtendedVirtual; //保留值,设为0
} MEMORYSTATUSEX,  *MEMORYSTATUSEX;
//单位  字节

GetSystemInfo()获得操作系统信息

void GetSystemInfo(LPSYSTEM_INFO lpSystemInfo);
lpSystemInfo 指向接收信息的SYSTEM_INFO结构的指针 。
typedef struct _SYSTEM_INFO {
  union {
    DWORD dwOemId;          //为了兼容性而保留的过时成员
    struct {
      WORD wProcessorArchitecture;
      WORD wReserved;       //该成员保留供将来使用。
    } DUMMYSTRUCTNAME;
  } DUMMYUNIONNAME;
  //页面大小以及页面保护和承诺的粒度。这是VirtualAlloc函数使用的页面大小 。
  DWORD     dwPageSize;
  //指向应用程序和动态链接库(DLL)可访问的最低内存地址的指针。   
  LPVOID    lpMinimumApplicationAddress;
  //指向应用程序和DLL可访问的最高内存地址的指针。
  LPVOID    lpMaximumApplicationAddress;
  //掩码,表示配置到系统中的一组处理器。位0是处理器0;位31是处理器31。
  DWORD_PTR dwActiveProcessorMask;
  //当前组中逻辑处理器的数量。
  DWORD     dwNumberOfProcessors;
  DWORD     dwProcessorType;
  //可以分配虚拟内存的起始地址的粒度。
  DWORD     dwAllocationGranularity;
  //与体系结构有关的处理器级别
  WORD      wProcessorLevel;
  //与体系结构有关的处理器修订版。下表显示了如何为每种处理器体系结构组合修订值。
  WORD      wProcessorRevision;
} SYSTEM_INFO, *LPSYSTEM_INFO;

SYSTEM_INDO详解

GetPerformanceInfo函数

BOOL GetPerformanceInfo(
  PPERFORMANCE_INFORMATION pPerformanceInformation,
  DWORD                    cb
);
//pPerformanceInformation  指向 接收性能信息的PERFORMANCE_INFORMATION结构的指针 。
//cb  PERFORMANCE_INFORMATION结构的大小 ,以字节为单位。
typedef struct _PERFORMANCE_INFORMATION {
  DWORD  cb;           //此结构的大小,以字节为单位。
  SIZE_T CommitTotal;  //系统当前提交的页面数。请注意,提交页面(将VirtualAlloc与MEM_COMMIT一起使用)会立即更改此值。但是,在访问页面之前不会对物理内存进行充电。
  SIZE_T CommitLimit;  //系统在不扩展页面文件的情况下可以提交的当前最大页面数。如果添加或删除内存,或者页面文件增加,缩小或添加,则此数字可以更改。如果分页文件可以扩展,则这是一个软限制。
  SIZE_T CommitPeak;  //自上次系统重新引导以来,同时处于提交状态的最大页面数。
  SIZE_T PhysicalTotal;  //实际物理内存量(以页为单位)。
  SIZE_T PhysicalAvailable; //当前可用的物理内存量(以页为单位)。这是可以立即重用而不必先将其内容写入磁盘的物理内存量。它是备用列表,空闲列表和零列表大小的总和。
  SIZE_T SystemCache;  //系统高速缓存内存量(以页为单位)。这是备用列表加上系统工作集的大小。
  SIZE_T KernelTotal; //分页和非分页内核池中当前的内存总和(以页为单位)。
  SIZE_T KernelPaged;  //分页内核池中当前的内存(以页为单位)。
  SIZE_T KernelNonpaged;  //当前未分页内核池中的内存(以页为单位)。
  SIZE_T PageSize;  //页面大小,以字节为单位。
  DWORD  HandleCount;  //当前打开的句柄数。
  DWORD  ProcessCount;  //当前的进程数。
  DWORD  ThreadCount;  //当前线程数。
} PERFORMANCE_INFORMATION, *PPERFORMANCE_INFORMATION, PERFORMACE_INFORMATION, *PPERFORMACE_INFORMATION;

CreateToolhelp32Snapshot函数

拍摄指定进程以及这些进程使用的堆,模块和线程的快照。

HANDLE CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID
);
参量(链接

dwFlags
要包含在快照中的系统部分。此参数可以是以下一个或多个值。

TH32CS_SNAPPROCESS  0x00000002
在快照中包括系统中的所有进程。要枚举进程,请参见 Process32First。
TH32CS_SNAPTHREAD  0x00000004
在快照中包括系统中的所有线程。要枚举线程,请参见 Thread32First。

th32ProcessID
要包含在快照中的进程的进程标识符。此参数可以为零以指示当前进程。当指定TH32CS_SNAPHEAPLIST,TH32CS_SNAPMODULE,TH32CS_SNAPMODULE32或TH32CS_SNAPALL值时,使用此参数。否则,它将被忽略并且所有进程都包含在快照中。
注意

  1. 如果指定的进程是Idle进程或CSRSS进程之一,则此函数将失败,并且最后一个错误代码为ERROR_ACCESS_DENIED,因为它们的访问限制会阻止用户级代码打开它们。
  2. 如果指定的进程是64位进程,而调用者是32位进程,则此函数将失败,并且最后一个错误代码是ERROR_PARTIAL_COPY(299)
返回值

如果函数成功,它将返回打开的句柄到指定的快照。

如果函数失败,则返回INVALID_HANDLE_VALUE。要获取扩展的错误信息,请调用 GetLastError。可能的错误代码包括ERROR_BAD_LENGTH。

Process32First函数

检索有关系统快照中遇到的第一个进程的信息。

BOOL Process32First(
  HANDLE           hSnapshot,
  LPPROCESSENTRY32 lppe
);
参量
hSnapshot
//从上一次调用CreateToolhelp32Snapshot函数返回的快照的 句柄。
lppe
//指向PROCESSENTRY32结构的指针 。它包含进程信息,例如可执行文件的名称,进程标识符和父进程的进程标识符。
返回值

如果进程列表的第一个条目已复制到缓冲区,则返回TRUE,否则返回FALSE。所述ERROR_NO_MORE_FILES误差值由返回 GetLastError函数功能如果不存在进程或快照不包含处理信息。

备注

调用应用程序必须将PROCESSENTRY32的dwSize成员 设置为该结构的大小(以字节为单位)。
要检索有关同一快照中记录的其他进程的信息,请使用 Process32Next函数。

OpenProcess功能

打开一个本地过程对象

HANDLE OpenProcess(
  DWORD dwDesiredAccess,  //访问权限
  BOOL  bInheritHandle,   //进程是否继承句柄
  DWORD dwProcessId       //要打开进程的本地标识符
);
返回值

如果函数成功,则返回值是指定进程的打开句柄。
如果函数失败,则返回值为NULL。要获取扩展的错误信息,请调用 GetLastError。

GetProcessMemoryInfo函数

检索有关指定进程的内存使用情况的信息。

BOOL GetProcessMemoryInfo(
  HANDLE                   Process,
  PPROCESS_MEMORY_COUNTERS ppsmemCounters,
  DWORD                    cb
);
参量
Process
//处理的句柄。句柄必须具有PROCESS_QUERY_INFORMATION或PROCESS_QUERY_LIMITED_INFORMATION访问权限以及
//PROCESS_VM_READ访问权限。有关更多信息,请参见流程安全性和访问权限。
//Windows Server 2003和Windows XP:  句柄必须具有PROCESS_QUERY_INFORMATION和PROCESS_VM_READ访问权限。

ppsmemCounters
//指向PROCESS_MEMORY_COUNTERS或PROCESS_MEMORY_COUNTERS_EX结构的指针,该指针 接收有关进程的内存使用情况的信息。

cb
//ppsmemCounters结构的大小 ,以字节为单位。

PROCESS_MEMORY_COUNTERS结构

包含内存统计信息

typedef struct _PROCESS_MEMORY_COUNTERS {
  DWORD  cb;                               //结构的大小,以字节为单位。
  DWORD  PageFaultCount;                   //页面错误数。
  SIZE_T PeakWorkingSetSize;
  SIZE_T WorkingSetSize;                   //当前的工作集大小,以字节为单位。
  SIZE_T QuotaPeakPagedPoolUsage;
  SIZE_T QuotaPagedPoolUsage;
  SIZE_T QuotaPeakNonPagedPoolUsage;
  SIZE_T QuotaNonPagedPoolUsage;
  SIZE_T PagefileUsage;
  SIZE_T PeakPagefileUsage;
} PROCESS_MEMORY_COUNTERS;

PROCESSENTRY32结构

描述在拍摄快照时系统地址空间中驻留的进程列表中的一项。

typedef struct tagPROCESSENTRY32 {
  DWORD     dwSize;            //结构的大小,以字节为单位。
  DWORD     cntUsage;
  DWORD     th32ProcessID;      //进程标识符
  ULONG_PTR th32DefaultHeapID;
  DWORD     th32ModuleID;
  DWORD     cntThreads;             //进程启动的执行线程数。
  DWORD     th32ParentProcessID;   //创建此进程的进程(其父进程)的标识符。
  LONG      pcPriClassBase;        //此进程创建的任何线程的基本优先级。
  DWORD     dwFlags;
  CHAR      szExeFile[MAX_PATH];    //进程的可执行文件的名称。
} PROCESSENTRY32;

MEMORY_BASIC_INFORMATION结构

typedef struct _MEMORY_BASIC_INFORMATION {
  PVOID  BaseAddress;               //指向页面区域基地址的指针。
  PVOID  AllocationBase;            //指向VirtualAlloc函数分配的页面范围的基地址的指针 。BaseAddress成员
                                    //指向的页面包含在此分配范围内。
  DWORD  AllocationProtect;
  SIZE_T RegionSize;                //从所有页具有相同属性的基地址开始的区域大小(以字节为单位)。
  DWORD  State;                     //区域中页面的状态。该成员可以是以下值之一。
  DWORD  Protect;
  DWORD  Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

VirtualQueryEx函数

检索有关指定进程的虚拟地址空间内的页面范围的信息。

SIZE_T VirtualQueryEx(
  HANDLE                    hProcess,
  LPCVOID                   lpAddress,
  PMEMORY_BASIC_INFORMATION lpBuffer,
  SIZE_T                    dwLength
);
  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值