加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

windows – x86 LargeAddressAware兼容性的单元测试

发布时间:2020-12-14 04:24:18 所属栏目:Windows 来源:网络整理
导读:对于win32可执行文件(x86),我们可以设置LargeAddressAware标志,以便在x64 Windows上运行时可以访问4 GB(而不是2 GB)的虚拟地址空间. 这看起来非常吸引人.但是,存在风险. 例如,请参阅: Drawbacks of using /LARGEADDRESSAWARE for 32 bit Windows executable
对于win32可执行文件(x86),我们可以设置LargeAddressAware标志,以便在x64 Windows上运行时可以访问4 GB(而不是2 GB)的虚拟地址空间.
这看起来非常吸引人.但是,存在风险.
例如,请参阅: Drawbacks of using /LARGEADDRESSAWARE for 32 bit Windows executables?

因此,让我们继续配置正在执行某些单元测试的系统,系统范围的注册表开关AllocationPreference设置为MEM_TOP_DOWN.
应该这样做,不应该吗?

它没有!
问题是Visual Studio的x86“测试运行器”(执行引擎)本身没有启用LAA.
这个父进程只能看到“较低”的2 GB VAS,我们的模块也将被测试.

VS2013.1中的示例

> mstest.exe生成QTAgent32.exe
> vstest.console.exe生成vstest.executionengine.x86.exe

所有这些都没有启用LAA!

那么使用支持LAA的x86测试运行器的推荐方法是什么?

这是一个用于检查LAA执行环境的小代码片段(VS单元测试,csharp).
除非它成功,否则您的测试环境不适合让您的单元测试(也)覆盖与LAA的兼容性:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestCheckEnv32LAA
{
    [TestClass]
    public class CheckEnv32LAA
    {
        #region [Native DLL import]

        [Flags()]
        public enum AllocationType : uint
        {
            COMMIT = 0x1000,RESERVE = 0x2000,RESET = 0x80000,LARGE_PAGES = 0x20000000,PHYSICAL = 0x400000,TOP_DOWN = 0x100000,WRITE_WATCH = 0x200000
        }

        [Flags()]
        public enum MemoryProtection : uint
        {
            EXECUTE = 0x10,EXECUTE_READ = 0x20,EXECUTE_READWRITE = 0x40,EXECUTE_WRITECOPY = 0x80,NOACCESS = 0x01,READONLY = 0x02,READWRITE = 0x04,WRITECOPY = 0x08,GUARD_Modifierflag = 0x100,NOCACHE_Modifierflag = 0x200,WRITECOMBINE_Modifierflag = 0x400
        }

        [StructLayout(LayoutKind.Sequential)]
        struct MEMORYSTATUSEX
        {
            public uint dwLength;
            public uint dwMemoryLoad;
            public ulong ullTotalPhys;
            public ulong ullAvailPhys;
            public ulong ullTotalPageFile;
            public ulong ullAvailPageFile;
            public ulong ullTotalVirtual;
            public ulong ullAvailVirtual;
            public ulong ullAvailExtendedVirtual;
        }

        [DllImport("kernel32.dll")]
        extern static void GlobalMemoryStatusEx(ref MEMORYSTATUSEX status);

        [DllImport("kernel32.dll",SetLastError = true)]
        public static extern UIntPtr VirtualAlloc(UIntPtr lpAddress,UIntPtr dwSize,AllocationType flAllocationType,MemoryProtection flProtect);

        #endregion

        public CheckEnv32LAA()
        {
        }

        [TestMethod]
        public void CheckEnvironment32LAA()
        {
            // check for a suitable environment to test modules for compatibility with LargeAddressAware (LAA):
            // 1) OS must be x64
            // 2) test runner must be x86
            // 3) test runner must be LAA enabled itself
            // 4) memory allocation (with manual TopDown flag) must happen beyond the 2 GB boundary
            // 5) memory allocation (with default settings) must happen beyond the 2 GB boundary
            //
            // RE 3) this requirement is true for "regular" unit tests (to test DLL modules). it does not apply
            // for any tests spawning the application (EXE) to be tested as a separate process.
            // 
            // RE 5) a failure indicates the following registry switch has not been set:
            // [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerMemory Management]
            // "AllocationPreference"=dword:00100000
            //
            // see:
            // https://stackoverflow.com/questions/2288728/

            String sParentProcName = Process.GetCurrentProcess().MainModule.FileName;

            //CHECK_1
            Assert.IsTrue(Environment.Is64BitOperatingSystem,"Test is not executing on x64 OS");

            //CHECK_2
            Assert.IsFalse(Environment.Is64BitProcess,"Test runner is not x86: " + sParentProcName);

            //CHECK_3
            MEMORYSTATUSEX tmpStatus = new MEMORYSTATUSEX();
            tmpStatus.dwLength = (uint)Marshal.SizeOf(typeof(MEMORYSTATUSEX));
            tmpStatus.ullTotalPhys = 0;
            GlobalMemoryStatusEx(ref tmpStatus);
            ulong uVM = tmpStatus.ullTotalVirtual;
            Assert.IsTrue(uVM > 0x80000000,"Test runner is not LAA enabled (max: " + uVM / (1024 * 1024) + "): " + sParentProcName);
            Assert.IsTrue(uVM <= 0x100000000,"Test runner is not x86 (max: " + uVM / (1024 * 1024) + "): " + sParentProcName);

            //CHECK_4
            UIntPtr pMem = UIntPtr.Zero;
            ulong uAddress = 0;
            pMem = VirtualAlloc(UIntPtr.Zero,(UIntPtr)1024,AllocationType.RESERVE | AllocationType.TOP_DOWN,MemoryProtection.READWRITE);
            uAddress = (ulong)pMem;
            Assert.IsTrue(uAddress > 0x80000000,"Test runner is not LAA enabled (highest: " + uAddress / (1024 * 1024) + "): " + sParentProcName);

            //CHECK_5
            pMem = VirtualAlloc(UIntPtr.Zero,AllocationType.RESERVE,"System-wide MEM_TOP_DOWN is not set (allocated at: " + uAddress / (1024 * 1024) + ")");
        }
    }
}
到目前为止,我只是遇到了混淆问题中列出的Microsoft二进制文件的建议(即使用editbin.exe手动“修补”它们).但这有以下缺点:

>为Visual Studio安装任何未来的Service Pack后,我需要重复修补
>我不能再并行测试:“常规”x86和“扩展”x86与LAA

似乎一个适当的长期解决方案必须由微软实施?:
http://visualstudio.uservoice.com/forums/196039-microsoft-test-tools/suggestions/5781437

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读