虚拟内存空间

  • 如今的 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. [源码分析] 消息队列 Kombu 之 Consumer

    [源码分析] 消息队列 Kombu 之 Consumer 目录 [源码分析] 消息队列 Kombu 之 Consumer 0x00 摘要 0x01 综述功能 0x02 示例代码 0x03 定义 3.1 ...

  2. [LeetCode 279.] Perfect Squres

    LeetCode 279. Perfect Squres DP 是笨办法中的高效办法,又是一道可以被好办法打败的 DP 题. 题目描述 Given a positive integer n, find ...

  3. 修改 Hosts 解决 Github 访问缓慢问题

    背景 最近访问 Github 经常出现访问速度慢的问题,甚至会出现无法连接的情况.有一天,在一次家常聊天中提到了这个事情,有一位热心的 Gitee 朋友就说:你改一下 Hosts 文件就可以了.修改了 ...

  4. Java 运行时数据区和内存模型

    运行时数据区是指对 JVM 运行过程中涉及到的内存根据功能.目的进行的划分,而内存模型可以理解为对内存进行存取操作的过程定义.总是有人望文生义的将前者描述为 "Java 内存模型" ...

  5. 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

    题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 输入描述: 输 ...

  6. ES6学习笔记(3)- 对象的功能性扩展

    一.什么是对象字面量 对象字面量就是创建对象(Object)的一种简单容易理解的方式,再通俗点就是所谓的键值对的集合.举个简单的例子: let book = { name: 'JavaScript', ...

  7. io流(对象流总结)

    对象流 对象流就是对引用数据类型进行操作 序列化:将对象的状态信息转换为可以存储或传输的形式的过程,因此类需要序列化后才可以存储到文件中 对象输出流: 很简单,就三句话,将把一个对象导入指定文件中,要 ...

  8. CPU 权限划分

    Intel的CPU将特权级别分为4个级别:RING0,RING1,RING2,RING3.Windows只使用其中的两个级别RING0和RING3,RING0只给操作系统用,RING3谁都能用.如果普 ...

  9. css盒模型以及如何计算盒子的宽度

    css盒模型以及如何计算盒子的宽度 盒模型 每个存在于可访问性树中的元素都会被浏览器绘制成一个盒子[1]. 每个盒子都可以看成由4部分组成,它们分别是 - 元素外边距(margin).元素边框(bor ...

  10. 从HotSpot VM源码看字符串常量池(StringTable)和intern()方法

    引言 字符串常量池(StringTable)是JVM中一个重要的结构,它有助于避免重复创建相同内容的String对象.那么StringTable是怎么实现的?"把字符串加入到字符串常量池中& ...