Вопрос

Вкл . Запись в Википедии о кольцевом буфере, там есть пример кода показываю взлом для UNIX системы, в которых смежная виртуальная память с фрагментом памяти является нанесенный на карту к той же самой физической памяти, таким образом реализуя кольцевой буфер без необходимости каких-либо memcpy ( память ), и т.д.Мне было интересно, есть ли способ сделать что-то подобное в Windows?

Спасибо, Фрейзер

Это было полезно?

Решение

На самом деле я не следил за всеми деталями примера в википедии.Имея это в виду, вы сопоставляете память в Windows с помощью Сопоставление файлов для создания и Файл MapViewOfFile, однако MapViewOfFile не позволяет вам указать базовый адрес для сопоставления. Просмотр карты Offileex может использоваться для указания базового адреса, поэтому, возможно, вы могли бы использовать аналогичный метод.

У меня нет никакого способа сказать, сработает ли это на самом деле:

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

Другие советы

О, привет, это та тема, которая меня очень беспокоила в последнее время.Мне нужен был posix-оптимизированный кольцевой буфер в Windows, в основном из-за его интерфейса произвольного доступа, но я никогда не имел ни малейшего представления о том, как его реализовать.Итак, код, предложенный @1800 INFORMATION, иногда работает, иногда нет, но идея в любом случае отличная.

Дело в том, что, MapViewOfFileEx иногда сбой с ERROR_INVALID_ADDRESS означает, что он не может сопоставить представление с pBuf+bufferSize.Это происходит потому, что MapViewOfFile called before выбирает свободное адресное пространство bufferSize длина (начиная с pBuf), но это не гарантирует, что это адресное пространство будет bufferSize*2 длинный.И зачем бы нам это понадобилось bufferSize*2 виртуальная память?Потому что наш кольцевой буфер нужно обернуть.Именно для этого и предназначен второй вид отображения.Когда указатель чтения или записи покидает первое представление, он переходит во второе представление (поскольку они смежны в памяти), но на самом деле все начинается сначала с того же отображения.

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)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top