Fork me on GitHub
内存管理相关的信息

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//结构体信息
);

  结构体如下:

复制代码
 1 typedef struct _SYSTEM_INFO {
 2     union {
 3         DWORD dwOemId;          // Obsolete field...do not use
 4         struct {
 5             WORD wProcessorArchitecture;//CPU结构
 6             WORD wReserved;//保留字段
 7         } DUMMYSTRUCTNAME;
 8     } DUMMYUNIONNAME;
 9     DWORD dwPageSize;//页面大小
10     LPVOID lpMinimumApplicationAddress;//最小内存地址
11     LPVOID lpMaximumApplicationAddress;//最大内存地址
12     DWORD_PTR dwActiveProcessorMask;//哪个CPU是活动的
13     DWORD dwNumberOfProcessors;//CPU数目
14     DWORD dwProcessorType;//CPU类型
15     DWORD dwAllocationGranularity;//保留的内存空间区域的分配粒度,
16     WORD wProcessorLevel; //CPU结构细节
17     WORD wProcessorRevision; //CPU等级
18 } SYSTEM_INFO, *LPSYSTEM_INFO;
复制代码

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

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

 

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

复制代码
 1 //获取系统参数
 2 #include "windows.h"
 3 #include "iostream"
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     SYSTEM_INFO sysinfo;//声明一个结构体
 9     GetSystemInfo(&sysinfo);
10 
11     cout<<"页面大小:"<<sysinfo.dwPageSize<<endl;
12     cout<<"最小内存地址:"<<sysinfo.lpMinimumApplicationAddress<<endl;
13     cout<<"最大内存地址:"<<sysinfo.lpMaximumApplicationAddress<<endl;
14     cout<<"保留的地址空间区域的分配粒度:"<<sysinfo.dwAllocationGranularity<<endl;
15     cout<<"CPU数目:"<<sysinfo.dwNumberOfProcessors<<endl;
16     cout<<"活动CPU:"<<sysinfo.dwActiveProcessorMask<<endl;
17     cout<<"处理器类型:"<<sysinfo.dwProcessorType<<endl;
18     cout<<"处理器结构:"<<sysinfo.wProcessorArchitecture<<endl;
19     cout<<"处理器等级:"<<sysinfo.wProcessorLevel<<endl;
20     cout<<"处理器版本:"<<sysinfo.wProcessorRevision<<endl;
21 
22     getchar();
23     return 0;
24 }
复制代码

 

  虚拟内存的状态GlobalMemoryStatus()

复制代码
 1 //这是旧版的函数
 2 void GlobalMemoryStatus(
 3     __out LPMEMORYSTATUS lpBuffer
 4     );
 5 typedef struct _MEMORYSTATUS {
 6     DWORD dwLength;
 7     DWORD dwMemoryLoad;
 8     SIZE_T dwTotalPhys;
 9     SIZE_T dwAvailPhys;
10     SIZE_T dwTotalPageFile;
11     SIZE_T dwAvailPageFile;
12     SIZE_T dwTotalVirtual;
13     SIZE_T dwAvailVirtual;
14 } MEMORYSTATUS, *LPMEMORYSTATUS;
复制代码

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

复制代码
 1 //新版函数更加强大
 2 BOOL GlobalMemoryStatusEx(
 3     __out LPMEMORYSTATUSEX lpBuffer
 4     );
 5 typedef struct _MEMORYSTATUSEX {
 6     DWORD dwLength;//结构体大小
 7     DWORD dwMemoryLoad;//已加载的内存比例
 8     DWORDLONG ullTotalPhys;//物理内存大小
 9     DWORDLONG ullAvailPhys;//当前可用物理内存大小
10     DWORDLONG ullTotalPageFile;//总的页面大小
11     DWORDLONG ullAvailPageFile;//当前可用的页面大小
12     DWORDLONG ullTotalVirtual;// 每个进程的地址空间中私有的总字节数
13     DWORDLONG ullAvailVirtual;// 进程的空闲地址空间的数量
14     DWORDLONG ullAvailExtendedVirtual;//保留,0
15 } MEMORYSTATUSEX, *LPMEMORYSTATUSEX;
复制代码

注意事项:

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

函数使用如下:

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

 

  地址空间状态VirtualQuery()

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

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

  参数介绍如下:

 

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

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

复制代码
1 //由一个进程查询另一个进程的信息
2 LPVOID VirtualAllocEx(
3     __in     HANDLE hProcess,//进程句柄
4     __in_opt LPVOID lpAddress,//查询地址
5     __in     SIZE_T dwSize,//与分配的页面大小
6     __in     DWORD flAllocationType,//分配类型
7     __in     DWORD flProtect //保护属性
8     );
复制代码
  如何查询地址状态
复制代码
 1 //如何查询地址状态
 2    cout<<"地址空间的状态"<<endl;
 3     MEMORY_BASIC_INFORMATION mbi;
 4     HANDLE hProcess = NULL;
 5     TCHAR path[1024] = {0};
 6     DWORD dwResult = VirtualQuery(hProcess,&mbi,sizeof(mbi));
 7     while(dwResult)  
 8     {  
 9         cout<<"内存地址起始地址:"<<hProcess<<endl;  
10         switch(mbi.State)  
11         {  
12         case MEM_COMMIT:  
13             cout<<"已经物理分配"<<endl;  
14             break;  
15         case MEM_RESERVE:  
16             cout<<"保留"<<endl;  
17             break;  
18         case MEM_FREE:  
19             cout<<"空闲没有分配"<<endl;  
20             break;  
21         default:  
22             break;  
23         }  
24         switch(mbi.Type)  
25         {  
26         case MEM_IMAGE:  
27             cout<<"该地址为文件镜像"<<endl;  
28             GetModuleFileName((HINSTANCE)hProcess,path,1024);  
29             cout<<path<<endl;  
30             break;  
31         case MEM_MAPPED:  
32             cout<<"已经映射了"<<endl;  
33             break;  
34         case MEM_PRIVATE:  
35             cout<<"私有的空间"<<endl;  
36             break;  
37         default:  
38             break;  
39         }  
40         getchar();
41         cout<<endl;  
42         hProcess=(PBYTE)hProcess+mbi.RegionSize;  
43         dwResult=VirtualQuery(hProcess,&mbi,sizeof(MEMORY_BASIC_INFORMATION));  
44     }
复制代码

 

 

Windows

 
摘要: 这一节看看内存管理相关的信息首先看看虚拟内存 虚拟地址空间 32位系统 --- 4GB = 232 64 位系统 ---- 16EB = 264 虚拟内存表 当一个应用程序从硬盘加载到RAM时,首先系统为应用程序保留一定的地址区域,将一些必须的数据加载到内存中,然后将一些不是必须的数据加载到页文件(虚拟内存)中,页文件的大小有操作系统控制。在程序运行过程中,如果需要某个文件,就先去RAM中寻找,如果寻找不到,就去页文件中寻找,如果还寻找不到就发出数据访问违规异常。 过程如下: 每个页文件的保护属性都不同,页文件的页面拥有不同的属性,包括 除了上面介绍的保护属性外,还有3个保...阅读全文
posted @ 2013-11-06 14:52 slq0378 阅读(301) | 评论 (0) 编辑
 
摘要: Win32平台上的Winsock编程,Winsock是一个与协议无关的接口。以下协议是我们需要了解的:网络协议的特征包括: 1、 面向消息 2、 面向连接和无线接 3、 可靠性和次序性 4、 从容关闭(这是指协议中断,连接不会立即中断) 5、 广播数据 6、 多播数据 7、 服务质量(QOS) 8、 部分消息(大数据进行分段发送,分段接受) 9、 路由选择(考虑协议是否可路由) 10、 字节序 11、 最大传输单元Windows支持的协议如下图Winsocket协议相关结构介绍//获得系统中安装的网络协议的相关信息int WSAEnumProtocols( _In...阅读全文
posted @ 2013-11-04 17:25 slq0378 阅读(416) | 评论 (0) 编辑
 
摘要: 邮槽和命名管道的使用方法也很简单,只需几个有限的函数就可以实现双方的通信。第三、邮槽 邮槽----进程间通信机制。 通过邮槽客户进程可以将消息通过广播给一个或多个服务进程。这是一个单向通信机制,缺点是只允许从客户机到服务器,优点也是这个原理,使客户机应用能够非常容易地将广播消息发送给一个或多个服务器应用。邮槽是一种无连接方式,是一种”不可靠“的数据传输。 邮槽名也使用UNC路径,第二个关键字是Mailslot,不可改变 \\\\server\\Mailslot\\[path]name 服务器实现过程: CreateMailslot();//创建一个邮槽句柄 ReadFile(...阅读全文
posted @ 2013-10-30 10:51 slq0378 阅读(466) | 评论 (2) 编辑
 
摘要: 在程序中加载位图有很多方法,各有各的好处。这里简单说一下在资源里和文件里加载的区别。第一、在资源里加载位图 这种方法就是在工程里的“资源视图”-->“添加资源”-->"Bitmap"-->"导入位图" 每个资源都会有一个资源ID,使用位图时就通过资源ID对他进行控制。 然后在设置背景图片是只需在OnPaint();里添加如下 CPaintDC dc(this); CRect rc; GetClientRect(&rc); CDC memDC;//目标内存 memDC.CreateCompatibleDC(&dc);/..阅读全文
posted @ 2013-10-29 14:49 slq0378 阅读(445) | 评论 (1) 编辑
 
摘要: 一直以来就是调试程序,生成的文件在debug或者release下,当没有其他资源文件时,这些程序也不用打包,直接就能够运行,但是程序中总会有一些额外的资源文件,视频啊,图片啊。这些需要打包在一个安装文件里,使用起来才更方便。 首先我们就用VS2010自带的工具Visual Studio Installer。 第一步,我们要新建一个工程,类型选择其他项目类型-->Visual Studio Installer-->安装向导-->名称(The Sun) 然后选择“为Windows应用程序创建一个安装程序” 接下来选择输出组:主输出,资源输出,生成输出 最后,可以现在附件,可以把视阅读全文
posted @ 2013-10-28 15:47 slq0378 阅读(556) | 评论 (6) 编辑
 
摘要: 这一次看看重定向器和如何使用Netbios函数获取本机mac地址5、获取Mac地址利用NCBASTAT命令实现,适配器状态命令会返回一个ADAPTER_STATUS结构,紧接着是大量NAME_BUFFER结构。 1 typedef struct _ADAPTER_STATUS { 2 UCHAR adapter_address[6];//这个就是mac地址 3 UCHAR rev_major; 4 UCHAR reserved0; 5 UCHAR adapter_type; 6 UCHAR rev_minor; 7 WORD ...阅读全文
posted @ 2013-10-23 18:07 slq0378 阅读(527) | 评论 (0) 编辑
 
摘要: 第一部分 传统网络API 传统的网络接口NetBIOS、重定向器、邮槽、命名管道等。第一,NetBIOS(Network Basic Input/Output System, NetBIOS)“网络基本输入/输出系统”,其中T C P / I P和I P X / S P X的协议上实施N e t B I O S编程接口。 1、LANA 编号 LANA 编号是NetBIOS协议进行通信的保障,每个网卡都会至少有一个LANA编号,两台机器进行通信时必须保证LANA编号一致才能进行。 2、NetBIOS 名字 NetBIOS 名字 是一个长度16字符的字符串,在Win32环境中,针对每个...阅读全文
posted @ 2013-10-22 16:45 slq0378 阅读(242) | 评论 (0) 编辑
 
摘要: 这里面的好多函数不能死记硬背,知道有这个函数就行,等用到了,再回来细看一、窗口管理函数包括以下几类:按钮函数(Button)Microsoft提供了对话框和控制来支持应用程序与用户之间的交互通讯。按钮就是一种控制,用户可通过点击按钮来向应用程序提供输入信息。插入标记函数(Caret)一个插入标记是位于窗口绘图区中的一个闪动的直线、方块或图标。插入标记通常用于指示文本或图形将插入的位置。Win32应用程序可以使用插入标记函数来创建一个插入标记,改变它的闪动频率,显示、隐藏插入标记,或重新设置插入标记的位置。 CreateCaret(),DestoryCaret(),HideCaret(),Se.阅读全文
posted @ 2013-10-21 17:39 slq0378 阅读(275) | 评论 (0) 编辑
 
摘要: 这本书绝对经典,看看定会增加不少知识。当然这本书有很多东西比《Windows程序设计第五版》中的更加详细。1、Unicode:宽字节字符集 这是一个国际的字符标准,16位,最大可支持65000个字符,完全可以应付全球所有语言。在Windows实际使用中,可以使用Micrsoft公司的API,也可以定义两个宏(UNICODE AND _UNICODE),就可以修改然后重新编译源文件。在实际使用中如果可以最好使用Unicode字符替代ANSI字符。2、C运行库对Unicode的支持 对于一些常用的数据类型和函数,Unicode都有与之对应。 如数据类型wchar_t, 定义为type...阅读全文
posted @ 2013-10-07 23:08 slq0378 阅读(503) | 评论 (1) 编辑

WinDbg配置和使用基础(转)


WinDbg是微软发布的一款相当优秀的源码级(source-level)调试工具,可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件。

1. WinDbg介绍:
     Debugging Tools and Symbols: Getting Started
http://www.microsoft.com/whdc/devtools/debugging/debugstart.mspx
     A word for WinDbg
http://mtaulty.com/communityserver/blogs/mike_taultys_blog/archive/2004/08/03/4656.aspx


2. WinDbg下载:
   Install Debugging Tools for Windows 32-bit Version
http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx
   Install Debugging Tools for Windows 64-bit Versions
http://www.microsoft.com/whdc/devtools/debugging/install64bit.mspx


3. 配置WinDbg:
      运行WinDbg->菜单->File->Symbol File Path->按照下面的方法设置_NT_SYMBOL_PATH变量:
在弹出的框中输入“C:\MyCodesSymbols; SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols”(按照这样设置,WinDbg将先从本地文件夹C:\MyCodesSymbols中查找Symbol,如果找不到,则自动从MS的Symbol Server上下载Symbols)。另一种做法是从这个Symbol下载地址中http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx,下载相应操作系统所需要的完整的Symbol安装包,并进行安装,例如我将其安装在D:\WINDOWS\Symbols,在该框中输入“D:\WINDOWS\Symbols”。(这里要注意下载的Symbols的版本一定要正确,在我的Win2003+Sp1上,我曾经以为安装Win2003+Sp2的Symbols可能会牛×点,但结果证明我错了,用WinDbg打开可执行文件时,提示“PDB symbol for mscorwks.dll not loaded;Defaulted to export symbols for ntdll.dll”的错误,我有重新装上Win2003+Sp1的Symbols, 现在一切运行正常^_^


4. 使用WinDbg:
      WinDbg提供了图形界面和命令行两种运行方式。这里介绍使用图形界面的WinDbg来调试应用程序:
      File->OpenExecutable->可以选择一个可执行文件进行调试;
      File->Attache to a Process->可以选择一个运行中的进程,并对其进行调试;

 
 
 


      至此,我们就可以在上图中用红色方框标记的文本框中输入各个功能指令了(有关指令的帮助文档,可以参考:Help->Contents-> Debugging Tools for Windows->Debuggers->Debugger Reference,该目录下列集了所有指令机器功能说明!)。

 
 

http://blog.csdn.net/bluebridge/archive/2007/05/10/1602749.aspx

 
WinDbg学习资料整理下载

      WinDbg是微软开发的免费源码级调试工具。Windbg可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件。在DotNet方面WinDbg是调试分析SSCLI的最佳工具,同时可以和SOS扩展一起调试分析.net程序。最近一段时间项目需要学习了一下,有感于WinDbg功能的强大。学习的过程并不一帆风顺,WinDbg自带的英文文档大而泛,网上资料也比较少,而WinDbg Not an ABBA Song。现在总算是入了点门,也收集了一些很好的资料,整理成一个CHM方便大家学习,时间仓促,整理得比较粗糙,大家凑合着看。这些文章均来自网络,版权归原作者所有。 
      下面三个包一个是我整理的文章,下面两个是WinDbg方面很不错的教程。

我整理的文章

windbg基础

kernel debug教程



托管调试 

介绍几个托管调试相关的博客,有很多典型案例可以学习 

大牛Tess的博客:blogs.msdn.com/tess/ 
johan:blogs.msdn.com/­johan/default.aspx 
maoni:blogs.msdn.com/­maoni/default.aspx 
Mike Taulty:mtaulty.com/blog/archive/­2004/08/06/628.aspx 

微软的官方指南-《Production Debugging for .NET Framework Applications》是非常不错的入门资料,还有例子可供练习,不可不读. 
 
 
分类: C++Windows
标签: C++Windows
posted on 2013-11-06 21:52  HackerVirus  阅读(282)  评论(0编辑  收藏  举报