虚拟内存空间

  • 如今的 Windows 操作系统不仅可以运行多个应用程序,还可以让每一个应用程序享受到约 4 GB 的虚拟内存空间(包括系统占用),假如内存为 4 GB 的话。那为什么 Window 可以做到呢,这归功于虚拟内存空间和页交换文件的快速交换才能实现这样的功能

0x02 使用虚拟内存空间

  • 那么程序如何才能使用虚拟内存空间呢,其实很简单,一般为这几个步骤:首先需要预定虚拟内存空间,因为 Windows 给出的原则是先预定才能够使用,其次需要在预定的地址空间调拨物理存储器,因为只有这样才能使用预定的虚拟内存地址空间,最后在使用完预定的虚拟内存地址空间后需要释放它,便于下一次使用
  • 来看看使用虚拟内存空间需要哪些函数:

    (1) VirtualAlloc:预定虚拟内存空间和调拨物理储存器 (2) VirtualFree:撤销物理储存器并且释放预定区域
  • 值得注意的是预定虚拟内存空间和调拨物理储存器使用的是用一个函数,分开使用便于理解,例子如下

注:虚拟内存空间并不是堆空间,堆空间是纯内存空间,而虚拟内存空间则是硬盘空间

#include <Windows.h>
#include <iostream>
#include <tlhelp32.h>
using namespace std; int main(int argc, char **argv)
{
PVOID AddressReserve, AddressUse; // 预定 100MB 大小的虚拟内存区域
AddressReserve = VirtualAlloc(NULL, 100 * 1024 * 1024, MEM_TOP_DOWN | MEM_RESERVE, PAGE_READWRITE); // 在预定完的虚拟内存区域调拨 1MB 大小的物理储存器
AddressUse = VirtualAlloc(AddressReserve, 1 * 1024 * 1024, MEM_COMMIT, PAGE_READWRITE);
memset(AddressUse, 'A', 1*1024*1024); MEMORY_BASIC_INFORMATION MemoryInfo = { 0 }; // 查询已经调拨物理储存器虚拟内存地址的状态
if (VirtualQuery(AddressUse, &MemoryInfo, sizeof(MemoryInfo)))
{
cout << "[*] 页面大小为: " << MemoryInfo.RegionSize << endl;
cout << "[*] 页面状态为: " << (HANDLE)MemoryInfo.State << endl;
} // 释放预定区域
VirtualFree(AddressReserve, 0, MEM_RELEASE);
return 0;
}
  • 值得注意的是使用 VirtualAlloc 预定虚拟内存地址空间的时候第二个参数必须传 MEM_RESERVE,而给预定地址空间调拨物理储存器的时候第二个参数必须传 MEM_COMMIT,如果是预定的同时调拨就传 MEM_RESERVE | MEM_COMMIT。在最后使用 VirtualFree 释放的时候,释放的是预定的全部虚拟内存地址,而不只是调拨物理储存器的虚拟内存地址,所以我给第二个参数传 0,给第三个参数传 MEM_RELEASE。为了更直观的看出虚拟内存空间的分配过程,可以观察分配时内存空间的变化:
  • 预定区域,成功返回基址为 0x79A50000:

  • 调拨物理储存器并覆盖为 ‘A’ 字符:



  • 释放预定区域:

  • 在程序的最后调用了 VirtualQuery 函数获取了刚刚调拨物理储存器的虚拟内存地址空间信息,打印结果如下:

  • 页面状态码的对应的页面状态,0x1000 表示该区域已经调拨了物理存储器
MEM_COMMIT
为0x1000
表示已在内存中或磁盘上的页面文件中为其分配了物理存储的已提交页面。
MEM_FREE
为0x10000
表示调用进程无法访问且可以分配的空闲页面。对于空闲页面,未定义AllocationBase,AllocationProtect,Protect和Type成员中的信息。
MEM_RESERVE
为0x2000
表示保留进程的虚拟地址空间范围而不分配任何物理存储的保留页面。对于保留页面,Protect成员中的信息未定义。

最新文章

  1. 常用的java正则表达式
  2. C#程序代码分析(第三周)
  3. VC++ 如何让ScrollView视图显示滚动条
  4. Redis安装和配置
  5. notpad++安装python插件
  6. 前端工作流程自动化——Grunt/Gulp 自动化
  7. JS 正则 获取URL参数
  8. 使用 Nginx 来反向代理多个 NoderCMS
  9. 最近遇到VS2013,在打开解决方案时,报如下错误: 未找到与约束
  10. ubuntu中KDE与GNOME安装切换
  11. 【转】NO.1、 appium之ios环境搭建
  12. spring boot+mybaits+mysql+generato(逆向工程)+前后台数据交互
  13. iis正确安装了,但是还是无法访问,这是iis和.net安装顺序问题,记录一下
  14. java idea导入ecli项目
  15. pyspider 启动错误遇到的一些坑
  16. zabbix的安装部署及自定义监控的实现
  17. shell 安装使用VIM
  18. C#窗体读取EXCEL存入SQL数据库
  19. (原创)Hibernate 使用过程中(尤其是多对多关联中的级联保存和级联删除)的注意事项(基于项目的总结)
  20. How to Acquire or Improve Debugging Skills

热门文章

  1. javaweb遇到的报错及解决方式
  2. C# 应用 - 封装类访问 Oracle 数据库
  3. addEventListener的第三个参数详解
  4. 搭建zabbix服务1
  5. golang 矩阵乘法、行列式、求逆矩阵
  6. 如何学习python爬虫
  7. 2.掌握numpy数组
  8. python常见错误和异常
  9. 8、Spring教程之静态代理/动态代理
  10. istio:在vs中实现ab测试和路径切割