Este artículo está participando en el "Proyecto Golden Stone. Comparte 60,000 premios en efectivo"
En el resumen del conocimiento de administración de memoria de Windows , mencioné
- Los procesos de 32 bits solo pueden usar 2 GB de memoria virtual en Windows
- Windows nos proporciona una forma de expandir la memoria virtual a 3GB
Este artículo continuará introduciendo
- Cómo expandir la memoria virtual
- ¿Cómo debemos implementar esta optimización para productos en línea?
Introducción al proceso de operación
BCDEdit \ establecer aumentar usuariova 3072
- En los sistemas superiores a XP, debe abrir cmd en modo administrador, ingresar
BCDEdit \set increaseuserva 3072
y se configurará el parámetro del sistema para aumentar el usuario 3072, donde 3072 significa 3 GB - En el sistema XP, debe modificar boot.ini
- Para obtener más información , consulte learn.microsoft.com/zh-cn/windo…
Verifique que la configuración esté en efecto
- Abra cmd nuevamente, ingrese
bcdedit
- Abra nuestra aplicación y use vmmap para ver la situación de la memoria.
En la imagen se puede ver que Total + Free no ha alcanzado los 3 GB, pero sigue siendo de 2 GB. ¿Qué está pasando? Además de configurar los parámetros del sistema, también necesitamos modificar los parámetros del enlazador de la aplicación. Veamos cómo hacerlo.
ESTABLECER PARÁMETRO DE CONECTOR/DIRECCIÓN GRANDE
- Tengo una versión anterior de Visual Studio, las versiones más nuevas deberían estar en una ubicación similar
- dumpbin.exe en el
Microsoft Visual Studio xx\VC\bin\
directorio - Abra cmd, ingrese
dumpbin /HEADERS {your exe path}
, puede verApplication can handle large (>2GB) address
que la configuración del parámetro del conector es exitosa
Doble verificación
- Como ves, Total + Gratis ha llegado a los 3GB
Hagamos los cálculos con cuidado ~ Total + Free es en realidad igual a 4 GB, entonces, ¿qué está pasando?
是因为我的 windows 操作系统为 64 位,在 64 位系统上运行 LargeAddress 模式的 32 位程序,虚拟内存会被扩展到 4GB,为什么会有这样的结果,后文会具体介绍。
64 位 Windows 操作系统运行 win32 程序
在 64 位系统上除了上面提到的虚拟内存会被扩展到 4GB,还有额外一点要注意: 不需要像 32 位系统一样设置 bcdedit,只需设置连接器参数 /LARGEADDRESSAWARE
即可。
32位进程虚拟内存地址空间不是一共只有 4GB,为什么在 64 位操作系统下能扩展到 4GB?这不是占用了内核空间么?
实际上,并没有占用内核空间地址。 原因是 32 位进程跑在 64 位系统时,实际是运行的 64 位进程,所以虚拟内存地址空间为 2^64
,低地址 4GB 远达不到内核空间的位置。下面附上一张 64 位进程的虚拟地址空间图
如何落地 LargeAddress 优化?
前面提到过,32 位系统下,需要通过 cmd 设置系统参数,我们总不能要求用户去设置吧?那么有没有能让用户花最小代价设置的方案呢?
我们能想到最直接的方案是,在代码中运行 bcdedit
命令,代码如下
ShellExecute(0, L"runas", L"BCDEdit.exe", L"/set increaseuserva 3072", NULL, SW_SHOWNORMAL);
复制代码
遗憾的是,这样做并不能成功,会报找不到 BCDEdit.exe
的错误,但直接在 cmd 中却能设置成功,这又是为什么呢?
因为我测试代码还是运行在 64 位系统上,在 64 位跑 32 位进程时,由于文件系统重定向机制(File System Redirection)程序无法访问 SysWOW64
文件夹,所以需要我们做些额外的操作
BOOL bWow64 = false;
IsWow64Process(GetCurrentProcess(), &bWow64);
if (bWow64)
{
PVOID OldValue = NULL;
if (Wow64DisableWow64FsRedirection(&OldValue))
{
ShellExecute(0, L"runas", L"BCDEdit.exe", L"/set increaseuserva 3072", NULL, SW_SHOWNORMAL);
Wow64RevertWow64FsRedirection(&OldValue);
}
}
复制代码
使用上述代码后,可以成功在 64 位系统上设置 bcdedit 系统参数了。更详细可以参考微软社区大神回答我的内容 learn.microsoft.com/en-us/answe…
¡Pero espera! ¿ No acabamos de decir que no es necesario bcdedit
configurar ? Bueno, me desvié en este paso, pero también aprendí más conocimiento en el proceso de resolver el problema. Además, los maestros de la comunidad de Microsoft también esperan que el interrogador pueda aprender más sobre algunos mecanismos del sistema de Windows.
También se debe mencionar que al ejecutar cmd a través del código, aparecerá una interfaz que le permitirá al usuario elegir si permite ejecutar cmd en modo administrador. Solo cuando el usuario acepta abrirlo, los parámetros del sistema se pueden configurar con éxito.
RIESGOS DE GRANDERRESSAWARE Y CÓMO EVITAR
Anteriormente presentamos en detalle cómo configurar el modo LargeAddress, entonces, ¿existe algún riesgo al hacerlo?
La conclusión es que cuando el código que no compatible con el modo LargeAddress asigna una dirección alta que supera los 2 GB, puede provocar el truncamiento del puntero o la dirección recién asignada es 0
No he investigado ejemplos específicos. Supongo que algunos programas asignarán direcciones fijas. Cuando la dirección supera los 2 GB, la dirección que se puede obtener se convierte en 0, o puede ser un tipo específico de puntero que solo puede abordar 2 GB. Porciones superior a 2 GB se truncan.
Entonces, ¿cómo podemos resolver el riesgo?
Necesitamos usar el modo de asignación de memoria de arriba hacia abajo para realizar una prueba completa . En circunstancias normales, la asignación de direcciones de memoria es de menor a mayor. Si se cambia de mayor a menor, podemos usar las direcciones por encima de 2 GB primero, y puede verificar el programa ¿Hay algún problema con el truncamiento del puntero en el archivo .
¿Entonces lo que hay que hacer?
Necesita modificar el registro [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]
Agregado AllocationPreference=00100000
, vea la siguiente figura para más detalles
¡Después de que la configuración sea exitosa, debe reiniciar la computadora para que surta efecto!
Para obtener más información, consulte stackoverflow.com/questions/2…