这一节看看内存管理相关的信息

首先看看虚拟内存

  虚拟地址空间

  32位系统  --- 4GB = 232

  64 位系统  ---- 16EB = 264

  虚拟内存表

  当一个应用程序从硬盘加载到RAM时,首先系统为应用程序保留一定的地址区域,将一些必须的数据加载到内存中,然后将一些不是必须的数据加载到页文件(虚拟内存)中,页文件的大小有操作系统控制。在程序运行过程中,如果需要某个文件,就先去RAM中寻找,如果寻找不到,就去页文件中寻找,如果还寻找不到就发出数据访问违规异常。

  过程如下:

  每个页文件的保护属性都不同,页文件的页面拥有不同的属性,包括

  除了上面介绍的保护属性外,还有3个保护属性标志,即PAGE_NOCACHE,PAGE_WRITECOMBINE和PAGE_GUARD。可以用OR逐位将它们连接,以便将这3个标志用于任何一个保护属性(PAGE_NOCACHE除外)。

  第一个保护属性标志PAGE_NOCACHE用于停用已提交页面的高速缓存。一般情况下最好不要使用该标志,因为它主要是供需要处理内存缓冲区的硬件设备驱动程序的开发人员使用的。

  第二个保护属性PAGE_WRITECOMBINE也是供设备驱动程序开发人员使用的。它允许把单个设备的多次写入合并在一起,以便提高运行性能。

  最后一个保护属性标志PAGE_GUARD可以在页面上写入一个字节时使应用程序收到一个通知(通过一个异常条件)。该标志有一些非常巧妙的用法。Windows2000在创建线程堆栈时使用该标志。

  虚拟内存的区域类型共有四个值,即空闲、私有、映像或映射。

  数据对齐

  数据对齐并不是操作系统的内存结构的一部分,而是CPU结构的一部分。

  当CPU访问正确对齐的数据时,它的运行效率最高。当数据大小的数据模数的内存地址是0时,数据是对齐的。

  当CPU试图读取的数据值没有正确对齐时,CPU可以执行两种操作之一。即它可以产生一个异常条件,也可以执行多次对齐的内存访问,以便读取完整的未对齐数据值。

  X86CPU和AlphaCPU的对齐方式不同。

  虚拟内存相关的函数

  获取系统信息相关的函数GetSystemInfo()

void WINAPI GetSystemInfo(
_Out_ LPSYSTEM_INFO lpSystemInfo//结构体信息
);

  结构体如下:

 typedef struct _SYSTEM_INFO {
union {
DWORD dwOemId; // Obsolete field...do not use
struct {
WORD wProcessorArchitecture;//CPU结构
WORD wReserved;//保留字段
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
DWORD dwPageSize;//页面大小
LPVOID lpMinimumApplicationAddress;//最小内存地址
LPVOID lpMaximumApplicationAddress;//最大内存地址
DWORD_PTR dwActiveProcessorMask;//哪个CPU是活动的
DWORD dwNumberOfProcessors;//CPU数目
DWORD dwProcessorType;//CPU类型
DWORD dwAllocationGranularity;//保留的内存空间区域的分配粒度,
WORD wProcessorLevel; //CPU结构细节
WORD wProcessorRevision; //CPU等级
} SYSTEM_INFO, *LPSYSTEM_INFO;

  其中与内存相关的参数如下:

  其他与内存无关的成员函数

  现在来看看如何使用这个函数 

 //获取系统参数
#include "windows.h"
#include "iostream"
using namespace std; int main()
{
SYSTEM_INFO sysinfo;//声明一个结构体
GetSystemInfo(&sysinfo); cout<<"页面大小:"<<sysinfo.dwPageSize<<endl;
cout<<"最小内存地址:"<<sysinfo.lpMinimumApplicationAddress<<endl;
cout<<"最大内存地址:"<<sysinfo.lpMaximumApplicationAddress<<endl;
cout<<"保留的地址空间区域的分配粒度:"<<sysinfo.dwAllocationGranularity<<endl;
cout<<"CPU数目:"<<sysinfo.dwNumberOfProcessors<<endl;
cout<<"活动CPU:"<<sysinfo.dwActiveProcessorMask<<endl;
cout<<"处理器类型:"<<sysinfo.dwProcessorType<<endl;
cout<<"处理器结构:"<<sysinfo.wProcessorArchitecture<<endl;
cout<<"处理器等级:"<<sysinfo.wProcessorLevel<<endl;
cout<<"处理器版本:"<<sysinfo.wProcessorRevision<<endl; getchar();
return ;
}

  虚拟内存的状态GlobalMemoryStatus()

 //这是旧版的函数
void GlobalMemoryStatus(
__out LPMEMORYSTATUS lpBuffer
);
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;

  //新版的函数,支持4G以上虚拟内存,64位宽度

 //新版函数更加强大
BOOL GlobalMemoryStatusEx(
__out LPMEMORYSTATUSEX lpBuffer
);
typedef struct _MEMORYSTATUSEX {
DWORD dwLength;//结构体大小
DWORD dwMemoryLoad;//已加载的内存比例
DWORDLONG ullTotalPhys;//物理内存大小
DWORDLONG ullAvailPhys;//当前可用物理内存大小
DWORDLONG ullTotalPageFile;//总的页面大小
DWORDLONG ullAvailPageFile;//当前可用的页面大小
DWORDLONG ullTotalVirtual;// 每个进程的地址空间中私有的总字节数
DWORDLONG ullAvailVirtual;// 进程的空闲地址空间的数量
DWORDLONG ullAvailExtendedVirtual;//保留,0
} MEMORYSTATUSEX, *LPMEMORYSTATUSEX;

注意事项:

  在调用GlobalMemoryStatus之前,必须将dwLength成员初始化为结构体的大小,即一个MEMORYSTATUS结构的大小。

函数使用如下:

 //获取虚拟内存状态
cout<<"\n虚拟内存状态\n"<<endl;
//虚拟内存状态
MEMORYSTATUSEX ms;
ms.dwLength = sizeof(MEMORYSTATUSEX);//这个参数必须首先初始化
GlobalMemoryStatusEx(&ms);
cout<<"结构体大小:"<<ms.dwLength<<endl;
cout<<"已加载的内存比例:"<<ms.dwMemoryLoad<<endl;
cout<<"物理内存大小:"<<ms.ullTotalPhys<<endl;
cout<<"可用内存大小:"<<ms.ullAvailPhys<<endl;
cout<<"总的页面数:"<<ms.ullTotalPageFile<<endl;
cout<<"可用页面数:"<<ms.ullAvailPageFile<<endl;
cout<<"每个进程的地址空间中私有的总字节数:"<<ms.ullTotalVirtual<<endl;
cout<<"进程的空闲地址空间的数量:"<<ms.ullAvailVirtual<<endl;

  地址空间状态VirtualQuery()

  通过该函数或获取进程地址空间的信息,如大小,存储类型,保护属性等。

 SIZE_T WINAPI VirtualQuery(
_In_opt_ LPCVOID lpAddress,//要查询的进程的地址空间信息的虚拟内存地址
_Out_ PMEMORY_BASIC_INFORMATION lpBuffer,//结构体
_In_ SIZE_T dwLength//本结构体的大小
);
//其中参数的详细情况如下
typedef struct _MEMORY_BASIC_INFORMATION {
PVOID BaseAddress;//进程地址
PVOID AllocationBase;//基地址
DWORD AllocationProtect;//保护属性
SIZE_T RegionSize;//所有页面大小
DWORD State;//相邻界面状态
DWORD Protect;//相邻界面保护属性
DWORD Type;//相邻界面的物理存储器类型
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

  参数介绍如下:

  由一个进程查询另一个进程的信息 VirtualAllocEx()

  调试程序会调用这个函数,查看其他进程的信息

 //由一个进程查询另一个进程的信息
LPVOID VirtualAllocEx(
__in HANDLE hProcess,//进程句柄
__in_opt LPVOID lpAddress,//查询地址
__in SIZE_T dwSize,//与分配的页面大小
__in DWORD flAllocationType,//分配类型
__in DWORD flProtect //保护属性
);
  如何查询地址状态
 //如何查询地址状态
   cout<<"地址空间的状态"<<endl;
MEMORY_BASIC_INFORMATION mbi;
HANDLE hProcess = NULL;
TCHAR path[] = {};
DWORD dwResult = VirtualQuery(hProcess,&mbi,sizeof(mbi));
while(dwResult)
{
cout<<"内存地址起始地址:"<<hProcess<<endl;
switch(mbi.State)
{
case MEM_COMMIT:
cout<<"已经物理分配"<<endl;
break;
case MEM_RESERVE:
cout<<"保留"<<endl;
break;
case MEM_FREE:
cout<<"空闲没有分配"<<endl;
break;
default:
break;
}
switch(mbi.Type)
{
case MEM_IMAGE:
cout<<"该地址为文件镜像"<<endl;
GetModuleFileName((HINSTANCE)hProcess,path,);
cout<<path<<endl;
break;
case MEM_MAPPED:
cout<<"已经映射了"<<endl;
break;
case MEM_PRIVATE:
cout<<"私有的空间"<<endl;
break;
default:
break;
}
getchar();
cout<<endl;
hProcess=(PBYTE)hProcess+mbi.RegionSize;
dwResult=VirtualQuery(hProcess,&mbi,sizeof(MEMORY_BASIC_INFORMATION));
}

Windows核心编程小结2的更多相关文章

  1. Windows核心编程小结3

    内存映射和堆栈 内存映射文件 内存映射文件可以用于3个不同的目的: 系统使用内存映射文件,以便加载和执行.exe和DLL文件.这可以大大节省页文件空间和应用程序启动运行所需的时间. 可以使用内存映射文 ...

  2. Windows核心编程小结1

    这本书绝对经典,看看定会增加不少知识.当然这本书有很多东西比<Windows程序设计第五版>中的更加详细. 1.Unicode:宽字节字符集 这是一个国际的字符标准,16位,最大可支持65 ...

  3. windows核心编程 - 线程同步机制

    线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...

  4. windows核心编程---第九章 同步设备IO与异步设备IO之同步IO

    同步设备IO 所谓同步IO是指线程在发起IO请求后会被挂起,IO完成后继续执行. 异步IO是指:线程发起IO请求后并不会挂起而是继续执行.IO完毕后会得到设备的通知.而IO完成端口就是实现这种通知的很 ...

  5. windows核心编程---第八章 使用内核对象进行线程同步

    使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...

  6. windows核心编程---第二章 字符和字符串处理

        使用vc编程时项目-->属性-->常规栏下我们可以设置项目字符集合,它可以是ANSI(多字节)字符集,也可以是unicode字符集.一般情况下说Unicode都是指UTF-16.也 ...

  7. 回忆读windows 核心编程

    看<windows 核心编程> 第五版到纤程了,下一章节即将介绍内存体系编程.如果做window平台下的开发,我感觉此书一定要读.记得开始讲解了window的基础,然后讲解内核对象.内核对 ...

  8. 《Windows核心编程》第5版 学习进度备忘

    学习资源:<Windows核心编程>第5版 知识基础支持: 本书与<Windows程序设计>第5版珍藏版结合很好,二者重叠内容不多,二者互补性强,而且相关方面的优秀书籍 跳过的 ...

  9. 【windows核心编程】 第八章 用户模式下的线程同步

    Windows核心编程 第八章 用户模式下的线程同步 1. 线程之间通信发生在以下两种情况: ①    需要让多个线程同时访问一个共享资源,同时不能破坏资源的完整性 ②    一个线程需要通知其他线程 ...

随机推荐

  1. SpringMVC项目的快速搭建

    Spring MVC提供了一个DispatcherServlet来开发Web应用.在Servlet2.5及2以下的时候只要在web.xml下配置<servlet>元素即可. 在Servle ...

  2. SQL Server(第二章) 字符串函数、日期时间函数、转换函数

    --1.CONCAT 函数:字符串连接(支持sql server2012 SQL规则 如果与NULL连接返回NILL) SELECT empid,CONCAT(firstname,lastname) ...

  3. 页面中插入视频兼容ie8以上的浏览器

    有时候页面中需要插入视频,如果不考虑ie8的话:就是直接用h5标签<video></video>就可以了: 但是有的时候需求是需要考虑ie8,这样我们就可以用插件,这种vide ...

  4. java Vamei快速教程17 多线程

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 多线程 多线程(multiple thread)是计算机实现多任务并行处理的一种方 ...

  5. js学习笔记之随机数

    一. JS获取任意两个数之间的随机数 参考:https://www.jb51.net/article/89629.htm 二.获取一个10–100范围的数 参考:https://zhidao.baid ...

  6. 复习C++_基础、函数、数组、字符串

    程序的开发过程 程序 源程序:用源语言写的,有待翻译的程序: 目标程序:源程序通过翻译程序加工以后生成的机器语言程序: 可执行程序:连接目标程序以及库中的某些文件,生成的一个可执行文件,例如Windo ...

  7. php 单例模式笔记

    <?php /** * 单例模式1. 它们必须拥有一个构造函数,并且必须被标记为private2. 它们拥有一个保存类的实例的静态成员变量3. 它们拥有一个访问这个实例的公共的静态方法单例类不能 ...

  8. @TransactionConfiguration过时与替代写法

    在使用了Spring的项目中做单元测试时,以前的标准写法是这样的: 但是在高版本的Spring框架中(Spring4.2以后),@TransactionConfiguration已经标注为过时的注解, ...

  9. CUDA常见问题与解答

    源 1.在SDK自带的例子程序中,发现SRC文件珜下有.cpp文件和.cu文件.这两种文件的关系和各自的作用是什么呀? 答:SDK自带例子中的.cpp文件主要是一些CPU端处理,或者是使用CPU计算对 ...

  10. 数据库引擎InnoDB和myisam的区别和联系

    1.ENGINE=InnoDB 数据库存储引擎,DEFAULT 默认,CHARSET=utf8 数据库字符编码 2.数据库的存储引擎, mysql中engine=innodb和engine=myisa ...