设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间12 现在时间12 缓存数据 做人啊,最要紧的是开心 你饿不饿,我去给你煮碗面 其实我不想给你煮面我只是想见你一面

做人啊,最要紧的是开心 你饿不饿,我去给你煮碗面 其实我不想给你煮面我只是想见你一面 -- 问你是否跟我走

查看: 365|回复: 0

.NET Core内存结构体系(Windows环境)底层原理解析

[复制链接]

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
25
主题
21
精华
0
金钱
78
积分
48
注册时间
2023-10-3
最后登录
2025-6-1

发表于 2025-6-1 05:32:53 | 显示全部楼层 |阅读模式

物理内存与虚拟内存物理内存

  • 物理内存(Physical Memory)
    定义:物理内存是计算机硬件中的实际RAM(如DDR5内存条),直接通过总线与CPU连接,用于临时存储运行中的程序和数据。
  • 虚拟内存(Virtual Memory)
    定义:由操作系统管理的抽象内存层,通过结合物理内存和磁盘空间(如页面文件或交换分区),为程序提供连续且独立的内存空间。

  1. 用户只需要与虚拟内存地址打交道,而无需关心数据到底分配在哪里
复制代码

1.png

眼见为实

2.png

物理页4K对齐

在Windows系统下,以4K为最小粒度,这个单位叫做

  1. 物理页
复制代码
,并以4K的整数倍分配内存。比如申请1k分配4k,申请5k分配8k

眼见为实

  1. void page4k() {
  2. for (int i = 0; i < 200; i++) {
  3. //1k 的占用
  4. LPVOID ptr = VirtualAlloc(NULL, 1024 * 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  5. printf("i=%d, 1k, address:%#0.8x \n", i + 1, ptr);
  6. }
  7. for (int i = 200; i < 400; i++) {
  8. //5k 的占用
  9. LPVOID ptr = VirtualAlloc(NULL, 1024 * 5, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  10. printf("i=%d, 5k, address:%#0.8x \n", i + 1, ptr);
  11. }
  12. getchar();
  13. }
复制代码

申请1k分配4k

3.png

申请5k分配8k

4.png

物理内存与虚拟内存如何映射?

Windows系统采用

  1. 二叉树结构
复制代码
(5层)来实现高效映射。

举个例子,某个32bit的内存地址为:0x77b01a42,其二进制为:01110,11110,11000,00001,101001000010

5.png

6.png

    1. 前20位
    复制代码
    用来构建
    1. 页表树
    复制代码
    ,实现物理页的的高效映射
    1. 后12位
    复制代码
    映射物理页的偏移量

操作系统以4K为一个单位对内存进行分组,4G内存=102410241024*4/(4/1024)=1048576物理页,如此庞大的物理页,,采用5层二叉树来提高索引效率

眼见为实:以notepad为例

任务管理:

7.png

Windbg:

8.png

可以看到非常明显的不同,任务管理器显示占用44.6mb内存,而windbg显示占用489.531mb内存,这是为什么呢?答:显示逻辑不同,任务管理器显示的是Private WorkingSet,指的是物理内存的地址,即

  1. 内存条上的内存
复制代码
,而Windbg是显示映射到的物理页,Commit指的是虚拟内存地址,这包括
  1. 内存条上的内存,pagefile,image
复制代码
三种

眼见为实:可视化观察 虚拟地址=>物理地址

使用windbg进入内核态,这很重要,大家可以猜猜原因。

随便找一个字符串的内存地址

9.png

  • 使用dp观察虚拟地址
  • 使用!vtop 观察映射信息
  • 使用!db观察物理地址

10.png

眼见为实:空指针区与用户态区

11.png

windows/linux在默认情况下,会开启ASLR,需要关闭此技术才能复现。ASLR 是一种针对缓冲区溢出攻击等内存攻击技术而设计的安全特性。在没有 ASLR 的情况下,程序加载到内存中的位置通常是固定的,攻击者可以预测程序中各种模块(如可执行文件、动态链接库等)的加载地址,进而利用这些固定地址来构造恶意代码进行攻击,比如在缓冲区溢出攻击中精准定位跳转地址来执行恶意指令。而启用 ASLR 后,操作系统在每次启动程序时会随机化程序的内存布局,包括可执行文件、动态链接库、堆、栈等的加载地址,使得攻击者难以准确预测内存地址,大大增加了攻击的难度。

Reserved与Commit

  • Reserved
    在虚拟地址上申请一段内存空间,此时操作系统也会同步创建
    1. 页表树
    复制代码
    ,但此时并
    1. 未映射到物理内存
    复制代码
    ,此时对该虚拟内存的读写会抛异常
  • Commit
    1. 页表树
    复制代码
    调配真实的
    1. 物理内存
    复制代码
    ,此时才能正常写入

眼见为实:Reserved

  1. void mem_reserved() {
  2. LPVOID ptr = VirtualAlloc(NULL, 4 * 1024, MEM_RESERVE, PAGE_READWRITE);
  3. *(int*)(ptr) = 10; //在首地址上写入内容。
  4. printf("num=%d", *(int*)ptr);
  5. }
复制代码

12.png

眼见为实:Commit

  1. void mem_commit() {
  2. LPVOID ptr = VirtualAlloc(NULL, 4 * 1024, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  3. *(int*)(ptr) = 10; //在首地址上写入内容。
  4. printf("num=%d", *(int*)ptr);
  5. }
复制代码

13.png

NT堆

NT堆是 Windows NT 内核引入的内存管理组件,主要负责进程内的堆内存分配与释放。在 Windows 系统里,进程可以使用 NT 堆来动态分配和管理内存,比如程序中使用 malloc()(C 语言)、new(C++) 等函数进行内存分配时,底层通常就依赖 NT 堆机制。

上面说到,VirtualAlloc方法它会一次性分配 64k 整数倍的内存段,内部对象按4k的内存页对齐.如果让application直接操作VirtualAlloc,难免会造成大量的内存浪费。为了提高内存性能与使用效率,Windows又提供了一层

  1. 抽象
复制代码
,以提供更细颗粒度的内存管理。它的名字叫做
  1. NT堆
复制代码

  • 在32bit平台上:8byte为一个分配粒度
  • 在64bit平台上:16btye为一个分配粒度

14.png

  • CRT堆:C运行时使用的堆,默认是对NT堆的简单封装
  • 托管堆:用作特殊用途的,自行实现的一套内存池管理机制。比如GC堆

从图中可以看出,使用NT与否取决于程序员本身。完全可以绕过NT堆,直接使用VirtualAlloc来分配内存,只要你接收内存浪费。

眼见为实:GC堆,底层使用VirtualAlloc分配内存

  1. static void Main(string[] args)
  2. {
  3. var rand = new Random();
  4. List<string> list = new List<string>();
  5. for (int i = 0; i < 100000; i++)
  6. {
  7. var str = string.Join(",", Enumerable.Range(0, rand.Next(1, 1000)));
  8. list.Add(str);
  9. Console.WriteLine($"i={i},length={str.Length}");
  10. }
  11. Console.ReadLine();
  12. }
复制代码

在bp KERNELBASE!VirtualAlloc 下断点

15.png

16.png

眼见为实:CRT堆/NT堆,底层使用VirtualAlloc分配内存

  1. #include <iostream>
  2. #include <Windows.h>
  3. void crt_c() {
  4. for (int i = 0; i < 10000000; i++) {
  5. int* ptr = (int*)malloc(sizeof(int) * 1000);
  6. *(ptr) = 10;
  7. printf("第 %d 次分配 \n", i);
  8. }
  9. }
复制代码

在 bp ntdll!NtAllocateVirtualMemory 下断点

17.png

到此这篇关于.NET Core内存结构体系(Windows环境)底层原理浅谈的文章就介绍到这了,更多相关.NET Core内存结构体系内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表