在进程空间使用虚拟内存(Windows 核心编程)
虚拟内存空间
- 如今的 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 核心编程)的更多相关文章
- 线程操作与进程挂起(Windows核心编程)
0x01 线程挂起与切换 对于挂起进程,挂起线程则比较简单,利用 ResumeThread 与 SuspendThread 即可,当线挂起时线程用户状态下的一切操作都会暂停 #include < ...
- Windows核心编程:第4章 进程
Github https://github.com/gongluck/Windows-Core-Program.git //第4章 进程.cpp: 定义应用程序的入口点. // #include &q ...
- C++Windows核心编程读书笔记
转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...
- 【转】《windows核心编程》读书笔记
这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...
- 《windows核心编程系列》十六谈谈内存映射文件
内存映射文件允许开发人员预订一块地址空间并为该区域调拨物理存储器,与虚拟内存不同的是,内存映射文件的物理存储器来自磁盘中的文件,而非系统的页交换文件.将文件映射到内存中后,我们就可以在内存中操作他们了 ...
- Windows核心编程随笔
最近在学习Windows底层原理,准备写个系列文章分享给大家,Michael Li(微软实习期间的Mentor,为人超好)在知乎回答过一些关于学习Windows原理的书籍推荐,大家可以拜读其中一本来入 ...
- windows核心编程 - 线程同步机制
线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...
- windows核心编程---第八章 使用内核对象进行线程同步
使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...
- 【windows核心编程】 第六章 线程基础
Windows核心编程 第六章 线程基础 欢迎转载 转载请注明出处:http://www.cnblogs.com/cuish/p/3145214.html 1. 线程的组成 ① 一个是线程的内核 ...
- 《Windows核心编程》读书笔记 上
[C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...
随机推荐
- 什么是内存对齐,go中内存对齐分析
内存对齐 什么是内存对齐 为什么需要内存对齐 减少次数 保障原子性 对齐系数 对齐规则 总结 参考 内存对齐 什么是内存对齐 弄明白什么是内存对齐的时候,先来看一个demo type s struct ...
- Java安全初学之反射
前言: 复现fastjson的时候深深意识到了需要好好学习一下Java和Java安全,激情的学习了一番java安全中重要的几部分:反序列化.反射.rmi.动态代理,从反射开始做个总结. 反射:java ...
- windows下MySQL如何完全卸载并安装行的版本
卸载本地mysql之前,请务必要先将需要的数据库备份 停止mysql 服务 windows键-->搜索服务 找到mysql 服务,并停止他 卸载mysql server 在控制面板--程序 找到 ...
- RabbitMQ简介、安装、基本特性API--Java测试
新的阅读体验地址:http://www.zhouhong.icu/post/141 本篇文章所有的代码:https://github.com/Tom-shushu/Distributed-system ...
- JavaCV 采集摄像头及桌面视频数据
javacv 封装了javacpp-presets库很多native API,简化了开发,对java程序员来说比较友好. 之前使用JavaCV库都是使用ffmpeg native API开发,这种方式 ...
- C# net Emgu.CV.World 人脸识别 根据照片将人脸抠图出来。
Emgu.CV.World 人脸识别 根据照片将人脸抠图出来.效果如下: 应用范围:配合摄像头,抓取的图像,抠出人脸照片,这样人脸照片的大小会很小,传输速度快.这样识别速度也就快. 目前我正在做百度人 ...
- C. 【例题3】畜栏预定
C . [ 例 题 3 ] 畜 栏 预 定 C. [例题3]畜栏预定 C.[例题3]畜栏预定 题解 考虑贪心 Code #include <bits/stdc++.h> using nam ...
- 经典变长指令SIB
前言 ModR/M字段是用来进行内存寻址的,可当地址形如DS:[EAX + ECX*2 + 12345678]时,仅仅靠ModR/M字段,是描述不出来的. 这时就在ModR/M后面增加一个SIB字节, ...
- Dynamics CRM安装教程八:Claims-based认证-外部访问配置(IFD配置)
内部访问配置完成后就剩下最关键的最后一步了,就是外部访问配置,这个配置好以后就可以让非域用户的计算机访问到我们的CRM系统了.言归正传开始进行配置打开CRM服务器的Dynamic CRM部署管理,选择 ...
- 多线程之Lock接口
之前写了一下synchronized关键字的一点东西,那么除了synchronized可以加锁外,JUC(java.util.concurrent)提供的Lock接口也可以实现加锁解锁的功能. 看完本 ...