對(duì) .NET程序2G虛擬地址緊張崩潰 的最后一次反思
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
一:背景1. 講故事最近接連遇到了幾起 2G 虛擬地址緊張 導(dǎo)致的程序崩潰,基本上 90% 都集中在醫(yī)療行業(yè),真的很無語,他們用的都是一些上古的 XP,Windows7 x86,我也知道技術(shù)人很難也基本無法推動(dòng)硬件系統(tǒng)和設(shè)備的升級(jí),這里蘊(yùn)含了巨大的人情世故。 寫這一篇的目的是想系統(tǒng)化的整理一下如何配置 3G 開關(guān)讓程序吃到更多的內(nèi)存,讓程序崩潰的不那么頻繁一些,以及如何驗(yàn)證是否成功開啟! 二:32位操作系統(tǒng)1. 測(cè)試代碼首先大家要有一個(gè)理念:就是 32bit系統(tǒng)上跑的程序,默認(rèn)只能吃到 2G 內(nèi)存,因?yàn)檫@涉及到公平,用戶態(tài)吃2G,內(nèi)核態(tài)吃2G,為了方便演示,向一個(gè) List 塞入 5000w 的 string,大概占用 2G 內(nèi)存,然后把程序跑在 Windows7 32bit 操作系統(tǒng)上。 static void Main(string[] args) { var list = new List<string>(); for (int i = 0; i < 50000000; i++) { list.Add(i.ToString()); if (i % 10000 == 0) { Console.WriteLine($"i={i}"); } } Console.WriteLine("ok"); Console.ReadLine(); } 從圖中可以清楚的看到當(dāng)內(nèi)存到了 有些朋友可能會(huì)問,這不是還沒到2G嗎?一般來說內(nèi)存到了 1.2G+ 的時(shí)候崩潰風(fēng)險(xiǎn)就會(huì)劇增,這個(gè)要謹(jǐn)記! 2. 如何解決剛才也說了,醫(yī)療行業(yè)現(xiàn)狀如此,只能通過人情世故去推動(dòng),那這 2G 數(shù)據(jù)真的無處安放嗎? 這時(shí)候就只能啟動(dòng) 3G 開關(guān),那如何啟動(dòng)呢?
這個(gè) Large Address Aware 字段俗稱大地址,途徑就是在 PE 頭里打開一個(gè)開關(guān),讓W(xué)indows加載器決定是否給程序打開 3G 的綠色通道。 當(dāng)然看 PE頭 的工具有很多,對(duì)于.NET程序個(gè)人感覺最好的就是用 DnSpy,它把 File Header 中的 Characteristics 字段具化了,我們選中 Large Address Aware 復(fù)選框然后保存,截圖如下:
在32bit操作系統(tǒng)上讓用戶態(tài)程序吃到 3G 內(nèi)存這對(duì)操作系統(tǒng)來說是非常謹(jǐn)慎的,畢竟這對(duì)內(nèi)核態(tài)是非常不公平的,言外之意就是讓出自己的 1G 給用戶態(tài),這騷操作可能就會(huì)把自己坑慘,謹(jǐn)慎起見需要人工開啟機(jī)器級(jí)別的 3G 開關(guān),命令如下: bcdedit /set IncreaseUserVa 3072 做了這兩步之后,繼續(xù)讓程序跑起來,截圖如下: 從圖中可以清晰的看到,終于有出息了。
3. 如何驗(yàn)證是否開啟了 3G這確實(shí)是一個(gè)好問題,最簡單的方式就是用 0:000> !address BaseAddr EndAddr+1 RgnSize Type State Protect Usage ----------------------------------------------------------------------------------------------- ... + bffde000 bffdf000 1000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE TEB [~0; aa4.fb8] + bffdf000 bffe0000 1000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE PEB [aa4] + bffe0000 bfff0000 10000 MEM_PRIVATE MEM_RESERVE PAGE_NOACCESS <unknown> 0:000> ? bfff0000/0x100000 Evaluate expression: 3071 = 00000bff 上面卦中的 如果有朋友想問如何驗(yàn)證 dump程序是否開啟了大地址,這個(gè)可以用windbg提供的 !dh 命令。 0:000> lm start end module name 001e0000 001e8000 ConsoleApp4 C (pdb symbols) D:\code\MyApplication\ConsoleApp4\obj\x86\Debug\ConsoleApp4.pdb 66dd0000 678c8000 mscorlib_ni (deferred) 678d0000 67e61000 mscorwks (deferred) 6c7a0000 6c83b000 msvcr80 (deferred) ... 0:000> !dh ConsoleApp4 File Type: execUTABLE IMAGE FILE HEADER VALUES 14C machine (i386) 3 number of sections EDB20AC7 time date stamp 0 file pointer to symbol table 0 number of symbols E0 size of optional header 122 characteristics executable App can handle >2gb addresses 32 bit word machine 如果看到上面卦中的 三:64位操作系統(tǒng)1. 如何吃更多內(nèi)存在 x64系統(tǒng)上就方便多了, 只需要做第一步開啟 接下來直接把剛才的 ConsoleApp4.exe 程序從 Windows7 x86 搬遷到 Windows 10 x64 系統(tǒng)上,然后用 windbg 附加運(yùn)行, 跑完后使用 0:007> !address BaseAddr EndAddr+1 RgnSize Type State Protect Usage ----------------------------------------------------------------------------------------------- + 0 c60000 c60000 MEM_FREE PAGE_NOACCESS Free ... + ff671000 ff680000 f000 MEM_FREE PAGE_NOACCESS Free + ff680000 ff6b3000 33000 MEM_MAPPED MEM_COMMIT PAGE_READONLY Other [NLS Tables] + ff6b3000 ffff0000 93d000 MEM_FREE PAGE_NOACCESS Free 0:007> ? ffff0000 /0x100000 Evaluate expression: 4095 = 00000fff 如果在你的卦中也看到了上面的 作者:一線碼農(nóng) 原文鏈接:cnblogs.com/huangxincheng/p/17853851.html 該文章在 2023/11/28 15:56:04 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |