Domanda

Sulla voce Wikipedia del Ring Buffer , c'è codice di esempio che mostra un hack per Sistemi UNIX per cui la memoria virtuale adiacente a un pezzo di memoria è mappata nella stessa memoria fisica, implementando così un buffer ad anello senza la necessità di memcpy , ecc. Mi chiedevo se esiste un modo per fare qualcosa di simile in Windows ?

Grazie, Fraser

È stato utile?

Soluzione

Non ho davvero seguito tutti i dettagli dell'esempio in Wikipedia. Tenendo presente ciò, mappi la memoria in Windows usando CreateFileMapping e MapViewOfFile , tuttavia MapViewOfFile non consente è necessario specificare un indirizzo di base per il mapping. MapViewOfFileEx può essere utilizzato per specificare un indirizzo di base forse potresti usare una tecnica simile.

Non ho modo di dire se funzionerebbe davvero:

// determine valid buffer size
SYSTEM_INFO info;
GetSystemInfo(&info);

// note that the base address must be a multiple of the allocation granularity
DWORD bufferSize=info.dwAllocationGranularity;

HANDLE hMapFile = CreateFileMapping(
             INVALID_HANDLE_VALUE,
             NULL,
             PAGE_READWRITE,
             0,
             bufferSize*2,
             L"Mapping");

BYTE *pBuf = (BYTE*)MapViewOfFile(hMapFile,
                    FILE_MAP_ALL_ACCESS,
                    0,                   
                    0,                   
                    bufferSize);
MapViewOfFileEx(hMapFile,
                    FILE_MAP_ALL_ACCESS,
                    0,                   
                    0,                   
                    bufferSize,
                    pBuf+bufferSize);

Altri suggerimenti

Oh hey, questo è l'argomento che mi ha preoccupato molto ultimamente. Avevo bisogno di ring buffer ottimizzato per posix su Windows, principalmente a causa della sua interfaccia ad accesso casuale, ma non avevo mai idea di come implementarlo. Ora, il codice proposto da @ 1800 INFORMATION funziona a volte, a volte no, ma l'idea è comunque ottima.

Il fatto è che MapViewOfFileEx a volte fallisce con ERROR_INVALID_ADDRESS, il che significa che non può mappare la vista su pBuf + bufferSize . Questo perché MapViewOfFile chiamato prima seleziona uno spazio di indirizzi libero di lunghezza bufferSize (a partire da pBuf ), ma non garantisce questo indirizzo spazio per essere bufferSize * 2 lungo. E perché dovremmo avere bisogno della memoria virtuale bufferSize * 2 ? Perché il nostro buffer ad anello deve essere avvolto. Ecco a cosa serve la seconda vista della 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)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top