虚拟内存空间

  • 如今的 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成员中的信息未定义。

在进程空间使用虚拟内存(Windows 核心编程)的更多相关文章

  1. 线程操作与进程挂起(Windows核心编程)

    0x01 线程挂起与切换 对于挂起进程,挂起线程则比较简单,利用 ResumeThread 与 SuspendThread 即可,当线挂起时线程用户状态下的一切操作都会暂停 #include < ...

  2. Windows核心编程:第4章 进程

    Github https://github.com/gongluck/Windows-Core-Program.git //第4章 进程.cpp: 定义应用程序的入口点. // #include &q ...

  3. C++Windows核心编程读书笔记

    转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...

  4. 【转】《windows核心编程》读书笔记

    这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...

  5. 《windows核心编程系列》十六谈谈内存映射文件

    内存映射文件允许开发人员预订一块地址空间并为该区域调拨物理存储器,与虚拟内存不同的是,内存映射文件的物理存储器来自磁盘中的文件,而非系统的页交换文件.将文件映射到内存中后,我们就可以在内存中操作他们了 ...

  6. Windows核心编程随笔

    最近在学习Windows底层原理,准备写个系列文章分享给大家,Michael Li(微软实习期间的Mentor,为人超好)在知乎回答过一些关于学习Windows原理的书籍推荐,大家可以拜读其中一本来入 ...

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

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

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

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

  9. 【windows核心编程】 第六章 线程基础

    Windows核心编程 第六章 线程基础 欢迎转载 转载请注明出处:http://www.cnblogs.com/cuish/p/3145214.html 1. 线程的组成 ①    一个是线程的内核 ...

  10. 《Windows核心编程》读书笔记 上

    [C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...

随机推荐

  1. 2.1 Python3基础-内置函数(print&input)

    >>返回主目录 源代码 # 内置函数:输入/输出 name = 'Portos' age = 18 sex = 'man' score = 99.5 print('Hello World! ...

  2. Python Flask框架路由简单实现

    Python Flask框架路由的简单实现 也许你听说过Flask框架.也许你也使用过,也使用的非常好.但是当你在浏览器上输入一串路由地址,跳转至你所写的页面,在Flask中是怎样实现的,你是否感到好 ...

  3. MySQL数据库之一

    数据库简介 数据库分类 关系型数据库(SQL):(狭义可以理解为行和列) MySQL,Oracle,Sql Server, DB2 通过表和表之间,行和列之间的关系进行存储 非关系型数据库(NoSQL ...

  4. 解决springMVC https环境 jstlview redirect时变为http请求的问题

    <property name="redirectHttp10Compatible" value="false" />

  5. SPOJ QTree【树链剖分】

    一 题目 QTREE 二 分析 第一道树链剖分的题,写的好艰难啊. 题意还是比较好理解的,就是在树上操作. 对于修改,题中要求的是单点修改,就算是直接树上操作也是非常简单的. 对于查询,查询的时候,是 ...

  6. postman接口自动化测试之添加Tests检查点

    一.概念 Postman的Tests本质上是JavaScript代码,通过我们编写测试代码,每一个Tests返回True,或是False,以判断接口返回的正确性. 其实,每一个Tests实际上就是一个 ...

  7. 采用React + Fabric + ImageMagick 实现大图片DIY定制

    一,需求背景: 某个印刷公司,有一系列的设计文件模板.接到客户订单时,就在这些设计文件模板上,做一些简单的定制,就能够满足客户的印刷需求. 如在设计文件模板上添加客户的Logo,二维码,联系方式等. ...

  8. 使用docker搭建sonarqube

    sonarqube是一款代码质量检查工具,使用sonar扫描我们写过的代码,可以有助于检查出代码的bug.规范性和健壮性,有助于提高我们的代码质量. 一.安装docker 安装完成之后,命令行输入 d ...

  9. 亲测有效JS中9种数组去重方法

    码文不易,转载请带上本文链接,感谢~ https://www.cnblogs.com/echoyya/p/14555831.html 目录 码文不易,转载请带上本文链接,感谢~ https://www ...

  10. ECharts使用指南

    第一步,引入ECharts: echars的引入十分简单,只需要在html中嵌入即可: <!DOCTYPE html> <html> <head> <scri ...