¿Cómo extender la memoria virtual del programa win32 a 3GB?

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é

  1. Los procesos de 32 bits solo pueden usar 2 GB de memoria virtual en Windows
  2. Windows nos proporciona una forma de expandir la memoria virtual a 3GB

Este artículo continuará introduciendo

  1. Cómo expandir la memoria virtual
  2. ¿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 3072y 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

  1. Abra cmd nuevamente, ingresebcdedit

bcdedit_check.png

  1. Abra nuestra aplicación y use vmmap para ver la situación de la memoria.

vmmap_bcdset.png

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

conjunto_enlace.png

  • Tengo una versión anterior de Visual Studio, las versiones más nuevas deberían estar en una ubicación similar

dump_bin.png

  • dumpbin.exe en el Microsoft Visual Studio xx\VC\bin\directorio
  • Abra cmd, ingrese dumpbin /HEADERS {your exe path}, puede ver Application can handle large (>2GB) addressque la configuración del parámetro del conector es exitosa

Doble verificación

dirección_grande_habilitar.png

  • 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 位进程的虚拟地址空间图

64bit_vm_disposición.png

如何落地 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 bcdeditconfigurar ? 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.

responder.png

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

tabla_reg.png

¡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…

Supongo que te gusta

Origin juejin.im/post/7166991733366980639
Recomendado
Clasificación