虚拟内存

——Windows核心编程学习手札之十四

系统信息

有些操作系统的值是根据主机而定的,如页面大小、分配粒度大小等,这些值不用硬编码形式,进程初始化时应检索这些值以使用。函数GetSystemInfo函数用于检索与主机相关的值:

VOID GetSystemInfo(LPSYSTEM_INFO psinf);

传递SYSTEM_INFO结构的地址,该函数将初始化结构成员并返回。

typedef struct _SYSTEM_INFO{

union{

DWORD dwOemId;//obsolete,do not use

Struct{

WORD wProcessorArchitecture;//用于指明处理结构,如Intel、Alpha、                                                Intel64位lpha64位,主要在windows2000中;

WORD wReserved;

};

};

DWORD dwPageSize;//用于显示CPU页面大小,如x86是4096字节;Alpha是8192字节;IA-64是8192字节;

LPVOID lpMinimumApplicationAddress;//用于给出每个进程的可用地址空间的最小内存地址,如Windows98中是4 194 304或0x00400000,因为每个进程的地址空间中下面4MB是不能使用的,用户方式的分区在该地址之上;如windows2000中,这个值是65 536或0x000100000,因为每个进程的地址空间中开头的64KB是空闲的;

LPVOID lpMaximumApplicationAddress;//用户给出每个进程的可用地址空间的最大内存地址,如windows98,这个地址是2 147 483 647或0x7FFFFFFF,因为共享内存映射文件和共享操作系统代码包含在上面的2GB分区中;如windows2000,这个地址是内核方式内存开始的地址,不足64KB;

DWORD_PTR dwActiveProcessorMask;//一个位屏蔽,用于指明哪个CPU是活动的;

DWORD dwNumberOfProcessors;//用于指明计算机中的CPU数目;

DWORD dwProcessorType;//用于指明处理器类型,如Intel386、486/Pentium,主要在windows98中;

DWORD dwAllocationGranularity;//显示保留的地址空间区域的分配粒度,目前,所有windows平台都是65 356;

WORD wProcessorLevel;//用于进一步细分处理器的结构,如设定Intel Pentium Pro或Pentium Ⅱ,主要用于windows2000;

WORD wProcessorRevision;//用于进一步细分处理器的级别,用于windows2000;

}SYSTEM_INFO,*LPSYSTEM_INFO;

对既定的系统,这些值都是相同的,不需要在既定的进程中多次调用函数,通过GetSystemInfo函数应该程序可以查询关于系统中的这些值。

示例代码:

#include "stdafx.h"

#include "windows.h"

#include "tchar.h"

void ShowCPUInfo(WORD wProcessorArchitecture,WORD wProcessorLevel,WORD wProcessorRevision)

{

TCHAR strInfo[256];

memset(strInfo,0,256);

/*PROCESSOR_ARCHITECTURE_INTEL

PROCESSOR_ARCHITECTURE_MIPS

PROCESSOR_ARCHITECTURE_UNKNOWN

PROCESSOR_ARCHITECTURE_SHX

PROCESSOR_ARCHITECTURE_ARM */

switch(wProcessorArchitecture)

{

case PROCESSOR_ARCHITECTURE_INTEL:

if(wProcessorLevel==4)

{

wsprintf(strInfo,_T("处理器类型: Intel 80486"));

}

else if(wProcessorLevel==5)

{

wsprintf(strInfo,_T("处理器类型: Pentium"));

}

else

{

wsprintf(strInfo,_T("处理器类型: PROCESSOR_ARCHITECTURE_INTEL"));

}

break;

case PROCESSOR_ARCHITECTURE_MIPS:

switch(wProcessorLevel)

{

case 3:

wsprintf(strInfo,_T("处理器类型: MIPS R3000"));

break;

case 4:

wsprintf(strInfo,_T("处理器类型: MIPS R4000"));

break;

case 5:

wsprintf(strInfo,_T("处理器类型: MIPS R5000"));

break;

default:

wsprintf(strInfo,_T("处理器类型: PROCESSOR_ARCHITECTURE_MIPS"));

break;

}

break;

case PROCESSOR_ARCHITECTURE_SHX:

wsprintf(strInfo,_T("处理器类型: PROCESSOR_ARCHITECTURE_SHX"));

break;

case PROCESSOR_ARCHITECTURE_ARM:

if(wProcessorLevel==4)

{

wsprintf(strInfo,_T("处理器类型: ARM version 4"));

}

else

{

wsprintf(strInfo,_T("处理器类型: PROCESSOR_ARCHITECTURE_ARM"));

}

break;

default:

wsprintf(strInfo,_T("处理器类型: PROCESSOR_ARCHITECTURE_UNKNOWN"));

break;

}

}

int main(int argc, char* argv[])

{

SYSTEM_INFO sinf;

GetSystemInfo(&sinf);

ShowCPUInfo(sinf.wProcessorArchitecture,sinf.wProcessorLevel,sinf.wProcessorRevision);

TCHAR szBuf[256];

wsprintf(szBuf,_T("页面文件大小: %d 或 0x%08x"),sinf.dwPageSize,sinf.dwPageSize);

wsprintf(szBuf,_T("进程的最小内存地址: %d 或 0x%08x"),sinf.lpMinimumApplicationAddress,sinf.lpMinimumApplicationAddress);

wsprintf(szBuf,_T("进程的最大内存地址: %d 或 0x%08x"),sinf.lpMaximumApplicationAddress,sinf.lpMaximumApplicationAddress);

wsprintf(szBuf,_T("当前活动的CPU: %d"),sinf.dwActiveProcessorMask);

return 0;

}

虚拟内存的状态

Windows函数GlobalMemoryStatus可用于检索关于当前内存状态的动态信息:

VOID GlobalMemoryStatus(LPMEMORYSTATUS pmst);

当调用GlobalMemoryStatus时,要传递MEMORYSTATUS结构的地址:

typedef struct _MEMORYSTATUS{

DWORD dwLength;

DWORD dwMemoryLoad;

SIZE_T dwTotalPhys;

SIZE_T dwAvailPhys;

SIZE_T dwTotalPageFile;

SIZE_T dwAvailPageFile;

SIZE_T dwTotalVirtual;

SIZE_T dwAvailVirtual;

}MEMORYSTATUS,*LPMEMORYSTATUS;

调用GlobalMemoryStatus函数之前,将dwLength成员初始化为用字节表示的结构的大小,即一个MEMORYSTATUS结构的大小。

如应用程序在内存大于4GB的计算机上运行,或者合计交换文件的大小大于4GB,可用新的GlobalMemoryStatusEx函数:

BOOL GlobalMemoryStatusEx(LPMEMORYSTATUSEX pmst);

函数传递新的结构MEMORYSTATUSEX:

typedef struct _MEMORYSTATUSEX{

DWORD dwLength;

DWORD dwMemoryLoad;

DWORDLONG ullTotalPhys;

DWORDLONG ullAvailPhys;

DWORDLONG ullTotalPageFile;

DWORDLONG ullAvailPageFile;

DWORDLONG ullTotalVirtual;

DWORDLONG ullAvailVirtual;

DWORDLONG ullAvailExtendedVirtual;

}MEMORYSTATUSEX,*LPMEMORYSTATUSEX;

新结构和原来的MEMORYSTATUS基本相同,差别在于新结构的所有成员的大小都是64位宽,因此它的值可以大于4GB,最后一个成员ullAvailExtendedVirtual,用于指明在调用进程的虚拟地址空间的极大内存(VLM)部分中未保留内存的大小。该VLM部分只适用于某些配置中的某些CPU结构。

Windows提供了一个函数,可以用来查询地址空间中内存地址的某些信息(如大小,存储器类型和保护属性等)。函数VirtualQuery:

DWORD VirtualQuery(

LPCVOID pvAddress,

PMEMORY_BASIC_INFORMATION pmbi,

DWORD dwLength);

Windows也提供了VirualQueryEx函数,用于使一个进程能够查询另一个进程的内存信息:

DWORD VirtualQueryEx(

HANDLE hProcess,

LPCVOID pvAddress,

PMEMORY_BASIC_INFORMATION pmbi,

DWORD dwLength);

结构体MEMORY_BASIC_INFORMATION在WinNT.h中定义:

typedef struct _MEMORY_BASIC_INFORMATION{

PVOID BaseAddress;

PVOID AllocationBase;

PVOID AllocationProtect;

SIZE_T RegionSize;

DWORD State;

DWORD Protect;

DWORD Type;

} MEMORY_BASIC_INFORMATION,* PMEMORY_BASIC_INFORMATION;

函数VirtualQuery的最后一个参数是dwLength,用于设定MEMORY_BASIC_INFORMATION结构的大小。VirtualQuery(Ex)函数返回拷贝到缓存中的字节的数量。根据pvAddress参数中传递的地址,VirtualQuery(Ex)函数将关于共享相同状态、保护属性和类型的相邻页面的范围信息填入MEMORY_BASIC_INFORMATION结构中。

虚拟内存——Windows核心编程学习手札之十四相关推荐

  1. 在应用程序中使用虚拟内存——Windows核心编程学习手札之十五

    在应用程序中使用虚拟内存 --Windows核心编程学习手札之十五 Windows提供了3种进行内存管理的方法: 1)  虚拟内存,最适合用来管理大量对象或结构数组: 2)  内存映射文件,最适合用来 ...

  2. DLL基础——Windows核心编程学习手札之十九

    DLL基础 --Windows核心编程学习手札之十九 Windows API中的所有函数都包含在DLL中,3个最重要的DLL是Kernel32.dll,它包含用于管理内存.进程和线程的各个函数:Use ...

  3. 堆栈——Windows核心编程学习手札之十八

    堆栈 --Windows核心编程学习手札之十八 堆栈可以用来分配许多较小的数据块,可以不考虑分配粒度和页面边界之类的问题,但分配和释放内存块的速度比其他机制要慢,并且无法直接控制物理存储器的提交和回收 ...

  4. 线程的堆栈——Windows核心编程学习手札之十六

    线程的堆栈 --Windows核心编程学习手札之十六 系统会在进程的地址空间内保存一些区域,同时也会在进程地址空间内为线程的堆栈保留区域.线程都有自己的堆栈,创建时,系统就保留一个堆栈空间区域,并将相 ...

  5. 未处理异常和C++异常——Windows核心编程学习手札之二十五

    未处理异常和C++异常 --Windows核心编程学习手札之二十五 当一个异常过滤器返回EXCEPTION_CONTINUE_SEARCH标识符时是告诉系统继续上溯调用树,寻找另外的异常过滤器,但当每 ...

  6. 插入DLL和挂接API——Windows核心编程学习手札之二十二

    插入DLL和挂接API --Windows核心编程学习手札之二十二 如下情况,可能要打破进程的界限,访问另一个进程的地址空间: 1)为另一个进程创建的窗口建立子类时: 2)需要调试帮助时,如需要确定另 ...

  7. DLL的高级操作技术——Windows核心编程学习手札之二十

    DLL的高级操作技术 --Windows核心编程学习手札之二十 显示加载DLL模块: HINSTANCE LoadLibrary(PCTSTR pszDLLPathName); HINSTANCE L ...

  8. 窗口消息——Windows核心编程学习手札之二十六

    窗口消息 --Windows核心编程学习手札之二十六 Windows允许一个进程至多建立10000个不同类型的用户对象(user object):图符.光标.窗口类.菜单.加速键表等,当一个线程调用一 ...

  9. 异常处理程序和软件异常——Windows核心编程学习手札之二十四

    异常处理程序和软件异常 --Windows核心编程学习手札之二十四 CPU负责捕捉无效内存访问和用0除一个数值这种错误,并相应引发一个异常作为对错误的反应,CPU引发的异常称为硬件异常(hardwar ...

最新文章

  1. 关于 synchronizeOnSession
  2. npc寻路问题 c++_《原神》游戏中最懒的NPC出现了,她要玩家找一朵甜甜花
  3. 814:The Letter Carrier's Rounds
  4. MVC扩展控制器工厂,通过继承DefaultControllerFactory来决定使用哪个接口实现,使用Ninject...
  5. boost::gregorian模块实现打印假期的测试程序
  6. SDNU 1330.Max Sum(最大子序列和)
  7. javafx之TableView的TaleCell
  8. Atmospheric Scattering
  9. SpringMVC 拦截器实现
  10. 图片热点的使用,html area 的用法
  11. Xcode 代码格式化/自动排版
  12. 银河水滴打响步态识别商用第一枪!3大产品1.35亿订单,工业视觉平台免费开放...
  13. Stage3D 入门资源汇总
  14. sqoop各类命令示范
  15. 安卓帧数监测软件_安卓查看帧数的软件
  16. 通过一个简单例子看懂遗传算法,附MATLAB代码
  17. 实力验证:金蝶EAS 8.2授权注册 (包含Apusic 9999连接数破解)
  18. kali-扫描主机-Nmap
  19. java this逃逸_java 中的 this 逃逸
  20. 【python爬虫】求人不如求己,自己动手写一个CSDN博客备份小工具?

热门文章

  1. java表底层生产工具_使用Java工具解决生产故障(一)-jcmd介绍
  2. Windows编程---------MessageBox
  3. R语言:怎么进行异常检测
  4. 201521123030《Java程序设计》 第2周学习总结
  5. 【Egret】WebSocket 的使用说明
  6. Android Studio项目结构
  7. 新手入门 keil MDK5 建立STM32工程
  8. 思考…求知(boolean和Boolean的区别)
  9. Android SQLite数据库增删改查操作
  10. Spring 整合 CXF