欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

.NET?Core內(nèi)存結(jié)構(gòu)體系(Windows環(huán)境)底層原理解析

 更新時(shí)間:2025年02月12日 08:48:40   作者:叫我安不理  
文章介紹了物理內(nèi)存和虛擬內(nèi)存的區(qū)別,以及Windows系統(tǒng)中虛擬內(nèi)存的管理方式,物理內(nèi)存是計(jì)算機(jī)硬件中的實(shí)際RAM,而虛擬內(nèi)存是由操作系統(tǒng)管理的抽象內(nèi)存層,感興趣的朋友一起看看吧

物理內(nèi)存與虛擬內(nèi)存物理內(nèi)存

  • 物理內(nèi)存(Physical Memory)
    定義:物理內(nèi)存是計(jì)算機(jī)硬件中的實(shí)際RAM(如DDR5內(nèi)存條),直接通過(guò)總線與CPU連接,用于臨時(shí)存儲(chǔ)運(yùn)行中的程序和數(shù)據(jù)。
  • 虛擬內(nèi)存(Virtual Memory)
    定義:由操作系統(tǒng)管理的抽象內(nèi)存層,通過(guò)結(jié)合物理內(nèi)存和磁盤(pán)空間(如頁(yè)面文件或交換分區(qū)),為程序提供連續(xù)且獨(dú)立的內(nèi)存空間。

用戶只需要與虛擬內(nèi)存地址打交道,而無(wú)需關(guān)心數(shù)據(jù)到底分配在哪里

眼見(jiàn)為實(shí)

物理頁(yè)4K對(duì)齊

在Windows系統(tǒng)下,以4K為最小粒度,這個(gè)單位叫做物理頁(yè),并以4K的整數(shù)倍分配內(nèi)存。比如申請(qǐng)1k分配4k,申請(qǐng)5k分配8k

眼見(jiàn)為實(shí)

void page4k() {
	for (int i = 0; i < 200; i++) {
		//1k 的占用
		LPVOID ptr = VirtualAlloc(NULL, 1024 * 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
		printf("i=%d, 1k, address:%#0.8x \n", i + 1, ptr);
	}
	for (int i = 200; i < 400; i++) {
		//5k 的占用
		LPVOID ptr = VirtualAlloc(NULL, 1024 * 5, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
		printf("i=%d, 5k, address:%#0.8x \n", i + 1, ptr);
	}
	getchar();
}

申請(qǐng)1k分配4k

申請(qǐng)5k分配8k

物理內(nèi)存與虛擬內(nèi)存如何映射?

Windows系統(tǒng)采用二叉樹(shù)結(jié)構(gòu)(5層)來(lái)實(shí)現(xiàn)高效映射。

舉個(gè)例子,某個(gè)32bit的內(nèi)存地址為:0x77b01a42,其二進(jìn)制為:01110,11110,11000,00001,101001000010

  • 前20位用來(lái)構(gòu)建頁(yè)表樹(shù),實(shí)現(xiàn)物理頁(yè)的的高效映射
  • 后12位映射物理頁(yè)的偏移量

操作系統(tǒng)以4K為一個(gè)單位對(duì)內(nèi)存進(jìn)行分組,4G內(nèi)存=102410241024*4/(4/1024)=1048576物理頁(yè),如此龐大的物理頁(yè),,采用5層二叉樹(shù)來(lái)提高索引效率

眼見(jiàn)為實(shí):以notepad為例

任務(wù)管理:

Windbg:

可以看到非常明顯的不同,任務(wù)管理器顯示占用44.6mb內(nèi)存,而windbg顯示占用489.531mb內(nèi)存,這是為什么呢?答:顯示邏輯不同,任務(wù)管理器顯示的是Private WorkingSet,指的是物理內(nèi)存的地址,即內(nèi)存條上的內(nèi)存,而Windbg是顯示映射到的物理頁(yè),Commit指的是虛擬內(nèi)存地址,這包括內(nèi)存條上的內(nèi)存,pagefile,image三種

眼見(jiàn)為實(shí):可視化觀察 虛擬地址=>物理地址

使用windbg進(jìn)入內(nèi)核態(tài),這很重要,大家可以猜猜原因。

隨便找一個(gè)字符串的內(nèi)存地址

  • 使用dp觀察虛擬地址
  • 使用!vtop 觀察映射信息
  • 使用!db觀察物理地址

眼見(jiàn)為實(shí):空指針區(qū)與用戶態(tài)區(qū)

windows/linux在默認(rèn)情況下,會(huì)開(kāi)啟ASLR,需要關(guān)閉此技術(shù)才能復(fù)現(xiàn)。ASLR 是一種針對(duì)緩沖區(qū)溢出攻擊等內(nèi)存攻擊技術(shù)而設(shè)計(jì)的安全特性。在沒(méi)有 ASLR 的情況下,程序加載到內(nèi)存中的位置通常是固定的,攻擊者可以預(yù)測(cè)程序中各種模塊(如可執(zhí)行文件、動(dòng)態(tài)鏈接庫(kù)等)的加載地址,進(jìn)而利用這些固定地址來(lái)構(gòu)造惡意代碼進(jìn)行攻擊,比如在緩沖區(qū)溢出攻擊中精準(zhǔn)定位跳轉(zhuǎn)地址來(lái)執(zhí)行惡意指令。而啟用 ASLR 后,操作系統(tǒng)在每次啟動(dòng)程序時(shí)會(huì)隨機(jī)化程序的內(nèi)存布局,包括可執(zhí)行文件、動(dòng)態(tài)鏈接庫(kù)、堆、棧等的加載地址,使得攻擊者難以準(zhǔn)確預(yù)測(cè)內(nèi)存地址,大大增加了攻擊的難度。

Reserved與Commit

  • Reserved
    在虛擬地址上申請(qǐng)一段內(nèi)存空間,此時(shí)操作系統(tǒng)也會(huì)同步創(chuàng)建頁(yè)表樹(shù),但此時(shí)并未映射到物理內(nèi)存,此時(shí)對(duì)該虛擬內(nèi)存的讀寫(xiě)會(huì)拋異常
  • Commit
    頁(yè)表樹(shù)調(diào)配真實(shí)的物理內(nèi)存,此時(shí)才能正常寫(xiě)入

眼見(jiàn)為實(shí):Reserved

void  mem_reserved() {
	LPVOID ptr = VirtualAlloc(NULL, 4 * 1024, MEM_RESERVE, PAGE_READWRITE);
	*(int*)(ptr) = 10;  //在首地址上寫(xiě)入內(nèi)容。
	printf("num=%d", *(int*)ptr);
}

眼見(jiàn)為實(shí):Commit

void  mem_commit() {
	LPVOID ptr = VirtualAlloc(NULL, 4 * 1024, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
	*(int*)(ptr) = 10;  //在首地址上寫(xiě)入內(nèi)容。
	printf("num=%d", *(int*)ptr);
}

NT堆

NT堆是 Windows NT 內(nèi)核引入的內(nèi)存管理組件,主要負(fù)責(zé)進(jìn)程內(nèi)的堆內(nèi)存分配與釋放。在 Windows 系統(tǒng)里,進(jìn)程可以使用 NT 堆來(lái)動(dòng)態(tài)分配和管理內(nèi)存,比如程序中使用 malloc()(C 語(yǔ)言)、new(C++) 等函數(shù)進(jìn)行內(nèi)存分配時(shí),底層通常就依賴 NT 堆機(jī)制。

上面說(shuō)到,VirtualAlloc方法它會(huì)一次性分配 64k 整數(shù)倍的內(nèi)存段,內(nèi)部對(duì)象按4k的內(nèi)存頁(yè)對(duì)齊.如果讓application直接操作VirtualAlloc,難免會(huì)造成大量的內(nèi)存浪費(fèi)。為了提高內(nèi)存性能與使用效率,Windows又提供了一層抽象,以提供更細(xì)顆粒度的內(nèi)存管理。它的名字叫做NT堆

  • 在32bit平臺(tái)上:8byte為一個(gè)分配粒度
  • 在64bit平臺(tái)上:16btye為一個(gè)分配粒度

  • CRT堆:C運(yùn)行時(shí)使用的堆,默認(rèn)是對(duì)NT堆的簡(jiǎn)單封裝
  • 托管堆:用作特殊用途的,自行實(shí)現(xiàn)的一套內(nèi)存池管理機(jī)制。比如GC堆

從圖中可以看出,使用NT與否取決于程序員本身。完全可以繞過(guò)NT堆,直接使用VirtualAlloc來(lái)分配內(nèi)存,只要你接收內(nèi)存浪費(fèi)。

眼見(jiàn)為實(shí):GC堆,底層使用VirtualAlloc分配內(nèi)存

static void Main(string[] args)
        {
            var rand = new Random();
            List<string> list = new List<string>();
            for (int i = 0; i < 100000; i++)
            {
                var str = string.Join(",", Enumerable.Range(0, rand.Next(1, 1000)));
                list.Add(str);
                Console.WriteLine($"i={i},length={str.Length}");
            }
            Console.ReadLine();
        }

在bp KERNELBASE!VirtualAlloc 下斷點(diǎn)

眼見(jiàn)為實(shí):CRT堆/NT堆,底層使用VirtualAlloc分配內(nèi)存

?
#include <iostream>
#include <Windows.h>
void crt_c() {
	for (int i = 0; i < 10000000; i++) {
		int* ptr = (int*)malloc(sizeof(int) * 1000);
		*(ptr) = 10;
		printf("第 %d 次分配 \n", i);
	}
}
?

在 bp ntdll!NtAllocateVirtualMemory 下斷點(diǎn)

到此這篇關(guān)于.NET Core內(nèi)存結(jié)構(gòu)體系(Windows環(huán)境)底層原理淺談的文章就介紹到這了,更多相關(guān).NET Core內(nèi)存結(jié)構(gòu)體系內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論