Кольцевой буфер Windows без копирования
-
06-07-2019 - |
Вопрос
Вкл . Запись в Википедии о кольцевом буфере, там есть пример кода показываю взлом для 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)