windows 虚拟内存

本文详细探讨了虚拟内存的原理,包括内存分页概念、映射方式、状态管理、操作系统内存管理机制以及相关API的使用,通过C++示例展示了如何修改常量内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        一、虚拟内存

        1、内存分页的概念:
内存分页是一种将物理内存划分成固定大小的块,并将虚拟内存映射到这些物理内存块的技术。在内存分页的实现中,每个物理内存块被称为一个页框,每个虚拟内存块被称为一个页面。操作系统将虚拟地址空间划分为固定大小的页面,并将其映射到物理地址空间中的页面框中。

内存分页的主要目的是实现虚拟内存,以提高系统的内存利用率。由于虚拟内存允许将页面换入换出到磁盘上,因此在物理内存不足时,可以将不常用的页面换出到磁盘上,从而释放物理内存,并为正在执行的进程提供足够的内存空间。同时,内存分页还可以使操作系统更加灵活地管理内存,以便实现内存保护和共享等功能。

在内存分页的实现中,操作系统通常会将每个页面映射到一个页表项中。页表项包含了虚拟页面的地址、页面的状态信息、页面的访问权限、页面所属的进程等信息。当CPU访问一个虚拟地址时,操作系统会根据该地址对应的页表项,将虚拟地址映射到物理地址,并检查对应的页面是否已经在物理内存中。如果页面不在物理内存中,操作系统就会触发一个缺页异常,将页面从磁盘上读取到物理内存中,并更新页表项。

内存分页是一种将虚拟内存映射到物理内存的技术,它实现了虚拟内存和内存保护等功能,提高了系统的内存利用率,并为操作系统提供了更加灵活的内存管理手段。

        2、操作系统分页概述: 

        操作系统如何管理内存? 

        作系统管理内存是将内存分成一页一页来管理的,每一页的大小是4K也就是0x1000

        4G的内存共有1M个页。

        使用了分页机制之后,4G的地址空间被分成了固定大小的页,每一页或者被映射到物理内存,或者被映射到硬盘上的交换文件中,或者没有映射任何东西。对于一般程序来说,4G的地址空间,只有一小部分映射了物理内存,大片大片的部分是没有映射任何东西。CPU用来把虚拟地址转换成物理地址的信息存放在叫做页目录和页表的结构里。

        3、虚拟内存状态: 

状态

空闲(FREE)

内存页不可用

保留(Reserve)

内存页被预定了,但为与物理内存做映射,还是不可用

提交(Commit)

内存被分配,并且与物理内存进行了映射,进程可以使用了

        当虚拟内存映射到物理内存时,有三种映射方式 

        4、内存映射方式: 

映射方式

描述

Private

进程私有内存,不被其他进程所共享,一般是堆,栈

Mapped

从别的内存映射而来

Image

从程序的PE映像映射而来。

        虚拟内存管理-内存属性:

Windows中,内存管理的最小单元是一个内存页 通常是0x1000=4kb

        5、内存分页属性: 

ReadOnly

只读

READ_WRITE

读写

EXECUTE

执行

EXECUTE_READ_WRITE

可读可写可执行

WRITE_COPY

写时拷贝

         6、页交换文件逻辑:

        程序访问虚拟内存地址,操作系统判断数据是否在内存中,如果在就从虚拟地址映射到的物理地址,如果不在就判断是否在页交换文件当中,如果在就查看物理内存是否有闲置空间,有的话,就将页交换文件载入到物理内存,如果没有闲置内存,就从物理内存中找到一个可以释放的页,然后将页保存到页交换文件中。

        7、虚拟内存相关API :

VirtualAlloc分配或者预定一块虚拟内存
VirtualAllocEx可以在其他进程分配或者预定一块内存
VirtualFree释放内存
VirtualFreeEx可以释放其他进程内存
VirtualLock锁定内存不能交换到硬盘
VirtualUnLock解锁
VirtualProtect修改内存读写执行属性
VirtualProtectEx可以修改其他进程内存属性
ReadProcessMemory读取远程进程内存
WriteProcessMemory写入数据到远程进程内存
VirtualQuery查询内存状态

 8、虚拟内存案例

        下面我们利用虚拟内存的特点来修改C++当中的常量:没错!就是那些你以为不可能被改动的const char*那些玩意

#include <iostream>
#include<Windows.h>
#include<cstring>
int main()
{
    const char* str = "码农今天在好好摆烂!\n";
    std::cout << "字符串常量修改前:" << str << std::endl;

    // 获取字符串所在内存区域的地址
    const void* addr = static_cast<const void*>(str);

    // 修改内存保护属性为可写属性
    //记得保存一下内存区域的原有访问属性,以便后续恢复他的属性,避免报错
    DWORD old_protect;
    VirtualProtect((char*)addr, strlen(str), PAGE_EXECUTE_READWRITE, &old_protect);
    // 修改字符串内容
    char* writable_str = const_cast<char*>(str);
    char* index = std::strstr(writable_str, "摆烂");
    if (index != nullptr) {
        std::memcpy(index, "学习!\0", 7);
    }
    // 输出修改后的字符串内容
    std::cout << "字符串常量修改后:" << str << std::endl;

    // 恢复内存保护属性为只读属性
    VirtualProtect((char*)addr, strlen(str), old_protect, &old_protect);

    return 0;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值