2010-12-01 8 views
8

Quiero mantener el espacio de direcciones virtuales reservado en mi proceso para la memoria que se usaba anteriormente, pero que actualmente no se necesita. Estoy interesado en la situación en la que el kernel de host es Linux y está configurado para evitar el exceso de compromiso (lo cual ocurre mediante la contabilidad detallada de toda la memoria comprometida).¿Mmap/mprotect-readonly cero páginas cuentan hacia la memoria comprometida?

Si sólo quiero evitar que los datos que mi aplicación ya no está utilizando de ocupar la memoria física o conseguir intercambiado en el disco (el desperdicio de recursos en ambos sentidos), puedo madvise el kernel que es innecesaria, o mmap nuevos cero páginas durante encima de eso. Pero ninguno de estos enfoques necesariamente reducirá la cantidad de memoria que cuenta como comprometida, lo que otros procesos no pueden usar.

¿Qué sucede si reemplazo las páginas con cero páginas nuevas que están marcadas como de solo lectura? Mi intención es que no cuenten para la memoria comprometida, y que luego pueda usar mprotect para hacerlos escribibles, y que fallaría si hacerlos escribibles superara el límite de memoria comprometida. Es mi entendimiento correcto? esto funcionara?

+1

Una página de solo lectura no se debe considerar en un cargo de confirmación de proceso (no tengo una referencia disponible, por lo que esta no es una respuesta), y Linux proporciona la bandera MAP_NORESERVE que debería proporcionarle un garantía. Pero tengo que preguntar: ¿por qué sientes la necesidad de reservar memoria que no está en uso? – Anon

+0

Cosas malas (tm) ocurrirían si las mismas direcciones virtuales fueran asignadas por 'mmap' (al azar) sin que el programa lo supiera. :-) En cuanto a 'MAP_NORESERVE', me preocupa que pueda evitar que las páginas se cuenten incluso después de que' mprotect' escribo más tarde. Supongo que podría simplemente 'mmap'-sobre ellos de nuevo con cero páginas nuevas. –

+0

¿Qué cosas malas pasarían? ¿Por qué su programa necesita nunca volver a utilizar el espacio de direcciones que se utilizó anteriormente? Eso parece muy inusual. – Angus

Respuesta

1

Si no está utilizando la página (leyéndola o escribiendo), no se comprometerá con su espacio de direcciones (solo reservado).

Pero su espacio de direcciones es limitado, por lo que no puede jugar como quiera o me gusta con él.

Consulte, por ejemplo, ElectricFence, que puede fallar para un gran número de asignaciones, debido a la inserción de "página nul page/guard" (memoria anónima sin acceso). Tener un vistazo a estos hilos: "mprotect(): No se puede asignar memoria": http://thread.gmane.org/gmane.comp.lib.glibc.user/538/focus=976052

+3

* se * cobrará al tamaño virtual, pero no a RSS. –

1

En Linux, asumiendo overcommit no ha sido desactivado, puede utilizar la bandera MAP_NORESERVE a mmap, lo que garantizará que la página en cuestión no se contabilizará como memoria asignada antes de acceder. Si el exceso se ha inhabilitado por completo, consulte a continuación las páginas de mapeo múltiple.

Tenga en cuenta que el comportamiento de Linux para cero páginas ha cambiado en ocasiones en el pasado; con algunas versiones de kernel, simplemente leyendo la página haría que se asignara. Con otros, una escritura es necesaria. Tenga en cuenta que los indicadores de protección no causan asignación directamente; sin embargo, pueden evitar que accidentalmente desencadene una asignación. Por lo tanto, para obtener resultados más confiables, debe evitar acceder a la página mprotect ing con PROT_NONE.

Como otra opción más portátil, puede asignar la misma página en varias ubicaciones. Es decir, crear y abrir un archivo temporal vacío, desvincularlo, ftruncate a un número razonable de páginas, luego mmap repetidamente en el desplazamiento 0 en el archivo. Esto garantizará que la memoria solo cuente una vez contra el uso de memoria de su programa. Incluso puede usar MAP_PRIVATE para auto-reasignar cuando escribe en la página.

Esto puede tener un mayor uso de memoria que la técnica MAP_NORESERVE (tanto para datos de seguimiento de kernel como para las páginas del archivo temporal en sí), así que recomendaría usar MAP_NORESERVE en cambio cuando esté disponible. Si utiliza esta técnica, intente hacer que la región sea asignada razonablemente grande (y colóquela en /dev/shm si está en Linux, para evitar el disco IO real). Cada llamada individual mmap consumirá una cierta cantidad de memoria del núcleo (no intercambiable) para rastrearla, por lo que es bueno mantener esa cuenta atrás.

+1

Información útil en general, pero 'MAP_NORESERVE' no es útil. Se ignora cuando overcommit está completamente deshabilitado. –

+0

¿Crees que mapear '/ dev/zero' funcionaría tan bien como un archivo temporal en tu propuesta? –

+0

@Zan, no. Los mapas '/ dev/zero' son los mismos que los mapas' MAP_ANON' ordinarios y, por lo tanto, se tendrán en cuenta como cualquier otra asignación de memoria. – bdonlan

Cuestiones relacionadas