Pregunta

En entrada de Wikipedia de Ring Buffer , hay código de ejemplo que muestra un truco para UNIX sistemas en los que la memoria virtual adyacente a una pieza de memoria es mapeado a la misma memoria física, implementando así un buffer de anillo sin la necesidad de memcpy , etc. Me preguntaba si hay una manera de hacer algo similar en Windows ?

Gracias, Fraser

¿Fue útil?

Solución

Realmente no seguí todos los detalles del ejemplo en wikipedia. Con eso en mente, usted asigna memoria en Windows usando CreateFileMapping y MapViewOfFile , sin embargo, MapViewOfFile no permite para especificar una dirección base para la asignación. MapViewOfFileEx se puede utilizar para especificar una dirección base tal vez podrías usar una técnica similar.

No tengo forma de saber si esto realmente funcionaría:

// 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);

Otros consejos

Oh, hey, este es el tema que me ha preocupado mucho últimamente. Necesitaba un búfer de anillo optimizado para posix 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 antes selecciona un espacio de dirección libre de bufferSize (a partir de pBuf ), pero no garantiza esta dirección espacio para ser bufferSize * 2 largo. ¿Y por qué necesitaríamos memoria virtual bufferSize * 2 ? Porque nuestro búfer de anillo debe ajustarse. Para eso 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 juntos en la memoria), pero en realidad comienza de nuevo en el mismo mapeo.

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)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top