Windows内存体系(3) -- 虚拟内存使用实例

虚拟内存方面的API属于页面粒度API,通过这些API分配的内存的最小粒度是64KB。另外通过前面的《Windows内存体系(2) – 页交换文件》文章,我们可以知道,这些API分配(调拨)的内存区域最初都是位于“页交换文件”上面,当程序对该区域的某些“页面”(对虚拟内存的管理以页面为单位进行的)进行读写时,才会将这些页面交换到物理内存上面。

《Windows内存体系(1) – 虚拟地址空间》中我们知道虚拟地址空间要经过预定调拨2个步骤之后才能使用,这2个步骤都可以通过VirtualAlloc函数实现:

LPVOID VirtualAlloc(
  LPVOID lpAddress, 
  DWORD dwSize, 
  DWORD flAllocationType, 
  DWORD flProtect 
); 

当预定或者调拨的空间我们不在需要时,我们需要调用VirtualFree来释放该地址空间:

BOOL VirtualFree(
  LPVOID lpAddress, 
  DWORD dwSize, 
  DWORD dwFreeType 
); 

下面是的示例演示了在预定、调拨、使用等操作前后,进程的各项内存的占用情况:

#include <windows.h>

int main()
{
    SIZE_T size = 1 << 30; // 1GB

    // 预定1GB的空间
    char *pVirtualAddress = (char *)VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_READWRITE);
    if (pVirtualAddress == NULL) {
        printf("Reserve 1GB failed.\n");
        return 1;
    }

    // 验证分配粒度是不是64KB
    int n = (long)pVirtualAddress % (64*1024);
    if (n == 0) {
        printf("分配粒度为64K\n");
    }

    printf("已经预定1GB\n");
    getchar(); // 暂停

    if (VirtualAlloc(pVirtualAddress, size, MEM_COMMIT, PAGE_READWRITE) == NULL) {
        printf("Commit 1GB failed.\n");
        return 1;
    }

    printf("已经调拨1GB\n");
    getchar(); // 暂停

    // 页面大小为4K,访问2560个页面,即2560*4K = 10MB
    // 
    for (int i = 0; i < 2560; i++) {
        char * p = pVirtualAddress + i * (4 * 1024);
        *p = 'A'; // 只访问每个页面的第一个字节
    }

    printf("已经使用前10MB\n");
    getchar(); // 暂停

    return 0;
}

在程序运行各个阶段进程的内存情况如下图:(“内存专用工作集”表示占用的物理内存的大小,“提交大小”表示调拨的页交换文件的大小)

这里写图片描述

china_jeffery CSDN认证博客专家 C/C++ Qt Node.js
持续学习者;
擅长开发开源组件及相关工具;
长期致力于应用各种IT新技术提升生产效率和解决实际问题;
china_jeffery@163#com
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值