Windows核心编程小结2
这一节看看内存管理相关的信息
首先看看虚拟内存
虚拟地址空间
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的更多相关文章
- Windows核心编程小结3
内存映射和堆栈 内存映射文件 内存映射文件可以用于3个不同的目的: 系统使用内存映射文件,以便加载和执行.exe和DLL文件.这可以大大节省页文件空间和应用程序启动运行所需的时间. 可以使用内存映射文 ...
- Windows核心编程小结1
这本书绝对经典,看看定会增加不少知识.当然这本书有很多东西比<Windows程序设计第五版>中的更加详细. 1.Unicode:宽字节字符集 这是一个国际的字符标准,16位,最大可支持65 ...
- windows核心编程 - 线程同步机制
线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...
- windows核心编程---第九章 同步设备IO与异步设备IO之同步IO
同步设备IO 所谓同步IO是指线程在发起IO请求后会被挂起,IO完成后继续执行. 异步IO是指:线程发起IO请求后并不会挂起而是继续执行.IO完毕后会得到设备的通知.而IO完成端口就是实现这种通知的很 ...
- windows核心编程---第八章 使用内核对象进行线程同步
使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...
- windows核心编程---第二章 字符和字符串处理
使用vc编程时项目-->属性-->常规栏下我们可以设置项目字符集合,它可以是ANSI(多字节)字符集,也可以是unicode字符集.一般情况下说Unicode都是指UTF-16.也 ...
- 回忆读windows 核心编程
看<windows 核心编程> 第五版到纤程了,下一章节即将介绍内存体系编程.如果做window平台下的开发,我感觉此书一定要读.记得开始讲解了window的基础,然后讲解内核对象.内核对 ...
- 《Windows核心编程》第5版 学习进度备忘
学习资源:<Windows核心编程>第5版 知识基础支持: 本书与<Windows程序设计>第5版珍藏版结合很好,二者重叠内容不多,二者互补性强,而且相关方面的优秀书籍 跳过的 ...
- 【windows核心编程】 第八章 用户模式下的线程同步
Windows核心编程 第八章 用户模式下的线程同步 1. 线程之间通信发生在以下两种情况: ① 需要让多个线程同时访问一个共享资源,同时不能破坏资源的完整性 ② 一个线程需要通知其他线程 ...
随机推荐
- SqlServer查询文件组被占用情况
在SqlServer中,删除一个文件组 alter database [xxxxx] remove filegroup FGMonthTurnIntroduceByMonth13 有时候会遇到如下报错 ...
- Visual Studio 更改护眼颜色
- java Vamei快速教程11 对象引用
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们之前一直在使用“对象”这个概念,但没有探讨对象在内存中的具体存储方式.这方面的 ...
- java模式
模式(Pattern) 模式(Pattern)的概念最早由建筑大师Christopher Alexander于二十世纪七十年代提出,应用于建筑领域,八十年代中期由Ward Cunningham和Ken ...
- UVALive 4731 Cellular Network(贪心,dp)
分析: 状态是一些有序的集合,这些集合互不相交,并集为所有区域.显然枚举集合元素是哪些是无法承受的, 写出期望的计算式,会发现,当每个集合的大小确定了以后,概率大的优先访问是最优的. 因此先对u从大到 ...
- 【洛谷1580】yyy loves Easter_Egg I(字符串处理题)
点此看题面 大致题意: 略.(一道模拟题,自己去看题面吧) 几个字符数组函数 纯粹是一道字符串处理题,就当是学了一下各种与字符数组相关的函数吧! \(gets()\):这个是比较常用的函数,就是读入一 ...
- 【转载】WEB架构师成长之路
本人也是coding很多年,虽然很失败,但也总算有点失败的心得,不过我在中国,大多数程序员都是像我一样,在一直走着弯路,如果想成为一个架构师,就必须走正确的路,否则离目标越来越远,正在辛苦工作的程序员 ...
- TypeScript 编译选项
编译选项 选项 类型 默认值 描述 --allowJs boolean false 允许编译javascript文件. --allowSyntheticDefaultImports boolean m ...
- day1总结
print("hello world") name='王维是傻屌' print(name) age_of_王维是傻屌 = 18 # type:用于判断变量的类型 str1 ='he ...
- 基于supersocket、C#对JT808协议进行解析构建gps监控平台服务端
GPS监控平台.车联网.物联网系统中GPRS网络数据的并发通讯和处理解析,主要功能有socket的UDP和TCP链路建立和维持,网络数据协议包接收与解析,分发上传到其他业务规则服务器,在物联网以及位置 ...