Oh, hey, questo è il tema che mi preoccupava molto ultimamente. Avevo bisogno di un ring buffer ottimizzato per posix su Windows, principalmente per la sua interfaccia ad accesso casuale, ma non avevo mai avuto alcuna idea su come implementarlo. Ora, il codice proposto da @ 1800 INFORMATION funziona a volte, a volte no, ma l'idea è comunque ottima.
La cosa è, MapViewOfFileEx
a volte non riesce con ERROR_INVALID_ADDRESS che significa che non può mappare la vista a pBuf+bufferSize
. Ciò è dovuto al fatto che il MapViewOfFile
chiamato prima seleziona uno spazio di indirizzi libero della lunghezza bufferSize
(a partire da pBuf
), ma non garantisce che lo spazio degli indirizzi sia bufferSize*2
lungo. E perché avremmo bisogno della memoria virtuale bufferSize*2
? Perché il nostro buffer ad anello deve essere avvolto. Questo è ciò per cui è la seconda vista mappatura. Quando il puntatore di lettura o scrittura lascia la prima vista, entra nella seconda vista (perché sono contigui in memoria), ma in realtà ricomincia dalla stessa mappatura.
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)
fonte
2012-11-19 07:38:41
Nell'esempio in questione non elimina la necessità di memcpy, si elimina la necessità di eseguire un'operazione DMA in due frammenti quando l'operazione passo oltre la fine della dotazione per il buffer. Funzionerà solo nello spazio degli indirizzi virtuali poiché dipende dalla disposizione di un buffer di dimensioni di pagina mappato su due posizioni nella memoria virtuale. – RBerteig
Errr ... sì, quello. Nel mio caso, sto passando il puntatore a un'altra funzione (libreria) che fa la scrittura, in modo che la funzione possa semplicemente fare la propria memcpy. –