2010-12-16 18 views
21

Adjunto constantemente a un archivo de cotizaciones de acciones (ints, longs, doubles, etc.). Tengo este archivo mapeado en la memoria con mmap.anexando a un archivo mapeado en memoria

¿Cuál es la forma más eficaz de hacer que los datos recién añadidos estén disponibles como parte de la asignación de memoria?

Entiendo que puedo abrir el archivo de nuevo (nuevo descriptor de archivo) y luego mmap para obtener los nuevos datos, pero que parece ser ineficaz. Otro enfoque que se me ha sugerido es asignar previamente el archivo en trozos de 1 mb, escribir en una posición específica hasta llegar al final y luego ftruntar el archivo en + 1 mb.

¿Hay otros enfoques?

Doest Boost ayuda con esto?

Respuesta

17

Boost.IOStreams tiene un tamaño fijo solamente memory mapped files, por lo que no ayudará con su problema específico. Linux tiene una interfaz mremap que funciona de la siguiente manera:

void *new_mapping = mremap(mapping, size, size + GROWTH, MREMAP_MAYMOVE); 
if (new_mapping == MAP_FAILED) 
    // handle error 
mapping = new_mapping; 

Esto es no portátil, sin embargo (y poco documentada). Mac OS X parece no tener mremap.

En cualquier caso, no es necesario volver a abrir el archivo, simplemente munmap y mmap nuevo:

void *append(int fd, char const *data, size_t nbytes, void *map, size_t &len) 
{ 
    // TODO: check for errors here! 
    ssize_t written = write(fd, data, nbytes); 
    munmap(map, len); 
    len += written; 
    return mmap(NULL, len, PROT_READ, 0, fd, 0); 
} 

Un esquema de asignación previa puede ser muy útil en este caso. Asegúrese de realizar un seguimiento de la longitud real del archivo y trunque una vez más antes de cerrar.

2

En cuanto a man page for mremap debería ser posible.

+1

mremap es específico de Linux, sin embargo. –

14

Sé que la respuesta ya ha sido aceptada, pero tal vez le ayude a otra persona si proporciono mi respuesta. Asigne un archivo grande antes de tiempo, digamos 10 GiB de tamaño. Crea tres de estos archivos antes de tiempo, los llamo volúmenes. Mantenga un registro de su última ubicación conocida en algún lugar, como en el encabezado, otro archivo, etc. y luego continúe añadiendo desde ese punto. Si alcanza el tamaño máximo del archivo y se queda sin espacio, cambie al siguiente volumen. Si no hay más volúmenes, crea otro volumen. Tenga en cuenta que probablemente haga esto unos volúmenes por delante para asegurarse de no bloquear sus archivos adjuntos a la espera de que se cree un nuevo volumen. Así es como lo implementamos donde trabajo para almacenar video/audio entrante continuo en un sistema de DVR para vigilancia. No desperdiciamos espacio para almacenar nombres de archivos para videoclips, por eso no usamos un sistema de archivos real y, en su lugar, pasamos al archivo plano y simplemente rastreamos compensaciones, información de cuadros (fps, tipo de cuadro, ancho/alto, etc.), tiempo grabado y canal de la cámara. Para ti el espacio de almacenamiento es barato para el tipo de trabajo que estás haciendo, mientras que tu tiempo es invaluable. Por lo tanto, tome todo lo que quiera con anticipación. Básicamente está implementando su propio sistema de archivos optimizado para sus necesidades. Las necesidades que los sistemas de archivos de uso general ofrecen no son las mismas necesidades que necesitamos en otros campos.

0

Mis 5cents, pero son más específicos de C. Haga el archivo normal, pero el tamaño enorme de mmap - por ejemplo, el archivo es, por ejemplo, 100K, pero mmap 1GB o más. Entonces puede acceder de manera segura a todo hasta el tamaño del archivo. El acceso sobre el tamaño del archivo dará como resultado un error. Si tiene sistema operativo de 32 bits, simplemente no haga que mmap sea demasiado grande, ya que ocupará su espacio de direcciones.

0

Si está utilizando boost/iostreams/device/mapped_file.hpp en las ventanas:

boost::filesystem::resize_file una excepción si un objeto de asignación de lectura está abierta, debido a la falta de privilegios de uso compartido. En su lugar, use windows-api para cambiar el tamaño del archivo en el disco, y la lectura mapped_file s aún puede estar abierta.

bool resize_file_wapi(string path, __int64 new_file_size) //boost::uintmax_t size 
{ 
    HANDLE handle = CreateFile(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 
    FILE_ATTRIBUTE_NORMAL, 0); 
    LARGE_INTEGER sz; 
    sz.QuadPart = new_file_size; 

    return handle != INVALID_HANDLE_VALUE 
    && ::SetFilePointerEx(handle, sz, 0, FILE_BEGIN) 
    && ::SetEndOfFile(handle) 
    && ::CloseHandle(handle); 
} 
Cuestiones relacionadas