哦,嘿,这是我最近很担心的话题。我需要在 Windows 上进行 posix 优化的环形缓冲区,主要是因为它的随机访问接口,但从来不知道如何实现它。现在,@1800 INFORMATION 提出的代码有时有效,有时无效,但无论如何这个想法很棒。
问题是,MapViewOfFileEx 有时会失败并显示 ERROR_INVALID_ADDRESS,这意味着它无法将视图映射到 pBuf+bufferSize。这是因为之前调用的MapViewOfFile 选择了一个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)