2011-12-23 11 views
5

memcpy/memmove duplicar (copiar los datos) desde el origen hasta el destino. ¿Existe algo para mover páginas de una dirección virtual a otra sin hacer una copia de byte real por byte de los datos de origen? Parece ser perfectamente posible para mí, pero, ¿algún sistema operativo realmente lo permite? Me parece extraño que los arreglos dinámicos sean un concepto tan extendido y popular, pero que hacerlos crecer copiando físicamente es una operación tan inútil. Simplemente no escala cuando se empieza a hablar acerca de los tamaños de matriz en los gigabytes (por ejemplo, imaginar el crecimiento de una gama de 100 GB en una matriz de 200 GB. Ese es un problema que es muy posible en los servidores de gama < $ 10K ahora.¿Algún sistema operativo permite mover la memoria de una dirección a otra sin copiarla físicamente?

void* very_large_buffer = VirtualAlloc(NULL, 2GB, MEM_COMMIT); 
// Populate very_large_buffer, run out of space. 
// Allocate buffer twice as large, but don't actually allocate 
// physical memory, just reserve the address space. 
void* even_bigger_buffer = VirtualAlloc(NULL, 4GB, MEM_RESERVE); 
// Remap the physical memory from very_large_buffer to even_bigger_buffer without copying 
// (i.e. don't copy 2GB of data, just copy the mapping of virtual pages to physical pages) 
// Does any OS provide support for an operation like this?  
MoveMemory(very_large_buffer, even_bigger_buffer, 2GB) 
// Now very_large_buffer no longer has any physical memory pages associated with it 
VirtualFree(very_large_buffer) 

Respuesta

6

hasta cierto punto, se puede hacer eso con mremap en Linux.

esa llamada jugadas con la tabla de página del proceso para hacer una reasignación de cero copia si puede. No es posible en todos los casos (la fragmentación del espacio de direcciones y simplemente la presencia de otras asignaciones existentes son un problema).

La página del manual en realidad dice lo siguiente:

mremap() cambia la asignación entre direcciones virtuales y páginas de memoria. Esto se puede usar para implementar un realloc muy eficiente (3).

+0

Parece que es exactamente lo que estoy buscando. Podría usar esto en Linux y una copia de memoria estúpida estándar en cualquier otro lugar. – Eloff

+1

O un realloc y espero que use un método similar debajo del capó. :) – onitake

2

Sí, es un uso común de archivos de memoria asignada a 'moverse' o copia de la memoria entre procesos mediante la asignación de diferentes vistas del archivo

0

Quiero decir, nunca se podría garantizar absolutamente que no habría memoria activa en los siguientes 100 GB, por lo que es posible que no pueda hacerlo contiguo.

Por otro lado, puede usar una matriz desigual (una matriz de matrices) donde las matrices no tienen que estar juntas (o incluso del mismo tamaño). Muchas de las ventajas de las matrices dinámicas pueden no escalar al reino de 100 GB.

+1

Según tengo entendido, las páginas de RAM físicas no necesitan ser contiguas, ese es el punto del direccionamiento virtual. Pero necesitaría 200 GB de espacio de direcciones virtuales no fragmentado (actualmente los procesos de 64 bits tienen 8 TB de espacio de direcciones en los sistemas operativos modernos, así que esto no debería ser un problema). – Eloff

1

Todos los sistemas POSIX son capaces de hacer esto. Si usa mmap con un descriptor de archivo (obtenido por open o shm_open) y no anónimamente, puede desasignarlo, truncarlo (reducirlo o hacerlo crecer) y luego asignarlo de nuevo. Es posible que a menudo obtengas una dirección virtual diferente para las mismas páginas.

+0

Corrígeme si me equivoco, pero quitar el mapeo escribiría todo sucio páginas de vuelta a ese archivo (¿perezoso?) Así que cuando vuelva a mapearlo, el acceso a las páginas podría requerir la lectura de ellas desde el archivo. Hay muchos detalles de implementación allí, pero evitar las copias de memoria causando IO de disco no es probable que sea una ganancia. Sin embargo, tengo curiosidad, ya que mmap se usa a menudo para compartir memoria entre procesos, ¿no debería ser posible hacer crecer (no reducir) el archivo y crear una segunda asignación del mismo archivo sin cerrar la primera asignación? Eso sería una copia de cero movimiento, creo. – Eloff

+0

Primero, si usa 'shm_open' no hay ningún archivo, por lo que no se puede escribir nada. E incluso para 'abrir', no creo que el mapeo vuelva a escribir las páginas, solo cerrar el descriptor de archivo lo haría cumplir. –

+0

Supongo que en el caso de shm_open no perderás los contenidos solo porque no los hayas mapeado, eso es interesante. Y tienes razón, supongo que las páginas sucias no se escribirían solo porque cerraste la asignación, todavía debería estar en el búfer de escritura del sistema. – Eloff

Cuestiones relacionadas