Oh hey, das ist das Thema, das mir in letzter Zeit sehr viel besorgt. Ich benötigte einen posix-optimierten Ring-Buffer unter Windows, vor allem wegen seiner Random-Access-Schnittstelle, hatte aber nie eine Idee, wie man ihn implementiert. Jetzt funktioniert der von @ 1800 INFORMATION vorgeschlagene Code manchmal, manchmal nicht, aber die Idee ist trotzdem großartig.
Die Sache ist, MapViewOfFileEx
schlägt manchmal mit ERROR_INVALID_ADDRESS was bedeutet, dass es die Ansicht nicht auf pBuf+bufferSize
zuordnen kann. Dies liegt daran, dass die zuvor genannte MapViewOfFile
einen freien Adressraum von bufferSize
Länge (ab pBuf
) auswählt, aber es garantiert nicht, dass dieser Adressraum bufferSize*2
lang ist. Und warum brauchen wir bufferSize*2
virtuellen Speicher? Weil unser Ringpuffer umbrechen muss. Dafür ist die zweite Mapping-Ansicht zuständig. Wenn der Lese- oder Schreibzeiger die erste Ansicht verlässt, tritt er in die zweite Ansicht ein (weil sie im Speicher zusammenhängend sind), aber tatsächlich beginnt er erneut bei der gleichen Zuordnung.
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)
Das Beispiel in Frage beseitigt nicht die Notwendigkeit für Memcpy beseitigen, ist es eine Notwendigkeit, eine DMA-Operation in zwei Fragmente zu tun, wenn der Betrieb über das Ende der Zuteilung für den Puffer Schritt würde. Es funktioniert nur im virtuellen Adressraum, da es darauf ankommt, einen seitengroßen Puffer anzuordnen, der auf zwei Plätze im virtuellen Speicher abgebildet wird. – RBerteig
Errr ... ja, das. In meinem Fall übergebe ich den Zeiger an eine andere (Bibliotheks-) Funktion, die das Schreiben ausführt, so dass die Funktion einfach ihr eigenes Memcpy ausführen kann. –