Oh hey, este es el tema que me preocupó mucho últimamente. Necesitaba un buffer de anillo posix optimizado en Windows, principalmente debido a su interfaz de acceso aleatorio, pero nunca tuve idea de cómo implementarlo. Ahora, el código propuesto por @ 1800 INFORMATION funciona a veces, a veces no, pero la idea es genial de todos modos.
El problema es que MapViewOfFileEx
a veces falla con ERROR_INVALID_ADDRESS lo que significa que no puede asignar la vista a pBuf+bufferSize
. Esto se debe a que el MapViewOfFile
llamado anteriormente selecciona un espacio libre de direcciones de bufferSize
de longitud (comenzando desde pBuf
), pero no garantiza que este espacio de direcciones sea bufferSize*2
de largo. ¿Y por qué necesitaríamos la memoria virtual bufferSize*2
? Porque nuestro buffer de anillo necesita envolverse. Esto es para lo que es la segunda vista de mapeo. Cuando el puntero de lectura o escritura sale de la primera vista, ingresa a la segunda vista (porque están contiguos en la memoria), pero en realidad comienza de nuevo en la misma asignación.
UINT_PTR addr;
HANDLE hMapFile;
LPVOID address, address2;
hMapFile = CreateFileMapping ( // create a mapping backed by a pagefile
INVALID_HANDLE_VALUE,
NULL,
PAGE_EXECUTE_READWRITE,
0,
bufferSize*2,
"Local\\mapping");
if(hMapFile == NULL)
FAIL(CreateFileMapping);
address = MapViewOfFile ( // find a free bufferSize*2 address space
hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
bufferSize*2);
if(address==NULL)
FAIL(MapViewOfFile);
UnmapViewOfFile(address);
// found it. hopefully it'll remain free while we map to it
addr = ((UINT_PTR)address);
address = MapViewOfFileEx (
hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
bufferSize,
(LPVOID)addr);
addr = ((UINT_PTR)address) + bufferSize;
address2 = MapViewOfFileEx (
hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
bufferSize,
(LPVOID)addr);
if(address2==NULL)
FAIL(MapViewOfFileEx);
// when you're done with your ring buffer, call UnmapViewOfFile for
// address and address2 and CloseHandle(hMapFile)
el ejemplo en cuestión no elimina la necesidad de establecimiento de memoria, que elimina la necesidad de realizar una operación de DMA en dos fragmentos cuando la operación daría un paso más allá del final de la asignación de la memoria intermedia. Solo funcionará en el espacio de direcciones virtuales, ya que depende de la organización de un búfer de tamaño de página que se asigna a dos lugares en la memoria virtual. – RBerteig
Errr ... sí, eso. En mi caso, estoy pasando el puntero a otra función (biblioteca) que hace la escritura, por lo que la función puede hacer su propia memcpy. –