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

首先看看虚拟内存

  虚拟地址空间

  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. linux下配置Nginx,支持thinkphp

    前言引入 一个刚入行的朋友,刚换工作,入职了一个新公司.新公司一个php开发,就是他.俨然老板把他当成公司扛把子了,把服务器都给了他,让他部署整个php的开发环境.那个朋友是wamp爱好者.然后面对l ...

  2. pta 编程题6 树的同构

    其它pta数据结构编程题请参见:pta 题目请参见:树的同构 因题目中左右子树是按照下标给出,因此用数组存放树是更好的方法. 判断两棵树是否同构:用递归的方法.如果当前两个结点都为空,则返回TRUE: ...

  3. 撸了个 django 数据迁移工具 django-supertube

    撸了个 django 数据迁移工具 django-supertube 支持字段映射和动态字段转化. 欢迎 star,issue https://github.com/FingerLiu/django- ...

  4. IOS 自定义Layer(图层)

    方式1: @interface NJViewController () @end @implementation NJViewController - (void)viewDidLoad { [sup ...

  5. Xcode Warning: “no rule to process file

    警告⚠️: warning: no rule to process file '/Users/Kingdev/Desktop/Git/finance_iOS/finance/Library/MBpro ...

  6. Vue3.0脚手架搭建

    https://www.jianshu.com/p/fbcad30031c2 vue3.0官网:https://cli.vuejs.org/zh/guide/ 介绍: notice: 这份文档是对应 ...

  7. mysql基础,DISTINCT关键字

  8. python3 练习题100例 (八)

    题目八:暂停一秒输出,并格式化当前时间. #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 题目八:暂停一秒输出,并格 ...

  9. Python9-IO模型-day41

    # 进程:启动多个进程,进程之间是由操作系统负责调用# 线程:启动多个线程,真正由被cpu执行的最小单位实际是线程# 开启一个线程,创建一个线程,寄存器.堆栈# 关闭一个线程# 协程# 本质上是一个线 ...

  10. stark组件前戏(3)之django路由分发的本质include

    django路由分发的三种方式 方式一: from django.urls import re_path, include urlpatterns = [ re_path(r'^web/', incl ...