Windows环缓冲区无需复制
-
06-07-2019 - |
解决方案
我并没有真正遵循维基百科中的示例的所有细节。考虑到这一点,您可以使用 CreateFileMapping - 在Windows中映射内存a>和 MapViewOfFile ,但MapViewOfFile不允许您可以为映射指定基址。 MapViewOfFileEx 可用于指定基址也许你可以使用类似的技术。
我无论如何都不知道这是否真的有效:
// 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);
其他提示
哦,嘿,这是最近让我很担心的话题。我在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)
不隶属于 StackOverflow