質問

Ring BufferのWikipediaエントリには、サンプルコード UNIX システムで、メモリに隣接する仮想メモリがマップ同じ物理メモリに、したがって memcpy などを必要とせずにリングバッファを実装します。 。 Windows に似たような方法があるかどうか疑問に思っていました。

ありがとう、フレイザー

役に立ちましたか?

解決

私は実際にウィキペディアの例のすべての詳細に従っていませんでした。それを念頭に置いて、 CreateFileMapping および 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 仮想メモリが必要なのでしょうか?リングバッファーをラップする必要があるためです。これが、2番目のマッピングビューの目的です。読み取りまたは書き込みポインターが最初のビューを離れると、(メモリー内で連続しているため)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