對 .NET程序2G虛擬地址緊張崩潰 的最后一次反思
當前位置:點晴教程→知識管理交流
→『 技術文檔交流 』
一:背景1. 講故事最近接連遇到了幾起 2G 虛擬地址緊張 導致的程序崩潰,基本上 90% 都集中在醫療行業,真的很無語,他們用的都是一些上古的 XP,Windows7 x86,我也知道技術人很難也基本無法推動硬件系統和設備的升級,這里蘊含了巨大的人情世故。 寫這一篇的目的是想系統化的整理一下如何配置 3G 開關讓程序吃到更多的內存,讓程序崩潰的不那么頻繁一些,以及如何驗證是否成功開啟! 二:32位操作系統1. 測試代碼首先大家要有一個理念:就是 32bit系統上跑的程序,默認只能吃到 2G 內存,因為這涉及到公平,用戶態吃2G,內核態吃2G,為了方便演示,向一個 List 塞入 5000w 的 string,大概占用 2G 內存,然后把程序跑在 Windows7 32bit 操作系統上。 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(); } 從圖中可以清楚的看到當內存到了 有些朋友可能會問,這不是還沒到2G嗎?一般來說內存到了 1.2G+ 的時候崩潰風險就會劇增,這個要謹記! 2. 如何解決剛才也說了,醫療行業現狀如此,只能通過人情世故去推動,那這 2G 數據真的無處安放嗎? 這時候就只能啟動 3G 開關,那如何啟動呢?
這個 Large Address Aware 字段俗稱大地址,途徑就是在 PE 頭里打開一個開關,讓Windows加載器決定是否給程序打開 3G 的綠色通道。 當然看 PE頭 的工具有很多,對于.NET程序個人感覺最好的就是用 DnSpy,它把 File Header 中的 Characteristics 字段具化了,我們選中 Large Address Aware 復選框然后保存,截圖如下:
在32bit操作系統上讓用戶態程序吃到 3G 內存這對操作系統來說是非常謹慎的,畢竟這對內核態是非常不公平的,言外之意就是讓出自己的 1G 給用戶態,這騷操作可能就會把自己坑慘,謹慎起見需要人工開啟機器級別的 3G 開關,命令如下: bcdedit /set IncreaseUserVa 3072 做了這兩步之后,繼續讓程序跑起來,截圖如下: 從圖中可以清晰的看到,終于有出息了。 3. 如何驗證是否開啟了 3G這確實是一個好問題,最簡單的方式就是用 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 上面卦中的 如果有朋友想問如何驗證 dump程序是否開啟了大地址,這個可以用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位操作系統1. 如何吃更多內存在 x64系統上就方便多了, 只需要做第一步開啟 接下來直接把剛才的 ConsoleApp4.exe 程序從 Windows7 x86 搬遷到 Windows 10 x64 系統上,然后用 windbg 附加運行, 跑完后使用 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 如果在你的卦中也看到了上面的 作者:一線碼農 原文鏈接:cnblogs.com/huangxincheng/p/17853851.html 該文章在 2023/11/28 15:56:04 編輯過 |
關鍵字查詢
相關文章
正在查詢... |