備忘録

備忘録

C++で複数プロセスから読み書き可能な共有メモリを作る

Ⅰ. はじめに

あるプロセスのメモリ空間には他のプロセスからアクセスする事ができません。
OpenProcess してアクセス権を得てもメモリ上のどのアドレスに何のデータが保存されているか簡単に分かりません。
この問題は複数プロセスで共有して使えるメモリ空間(共有メモリ)を利用することで解決できます。

Ⅱ. サンプル

  • 1. 1秒毎に共有メモリにデータを書き込むだけのプログラム
  • 2. 1秒毎に共有メモリからデータを読み込むだけのプログラム

上記2つのサンプルです。

1. 共有メモリにデータを書き込むだけのプログラム
#include <windows.h>
#include <iostream>

using namespace std;

void main()
{
  auto name = "hoge";
  auto size = 4;

  HANDLE hSharedMemory = CreateFileMapping(NULL, NULL, PAGE_READWRITE, NULL, size, name);
  auto pMemory = (int*)MapViewOfFile(hSharedMemory, FILE_MAP_ALL_ACCESS, NULL, NULL, size);

  for (int i = 0; i < 10; i++)
  {
    *pMemory = i;
    cout << i << endl;
    Sleep(1000);
  }

  UnmapViewOfFile(pMemory);
  CloseHandle(hSharedMemory);
}
2. 共有メモリからデータを読み込むだけのプログラム
#include <windows.h>
#include <iostream>

using namespace std;

void main()
{
  auto name = "hoge";
  auto size = 4;

  HANDLE hSharedMemory = CreateFileMapping(NULL, NULL, PAGE_READWRITE, NULL, size, name);
  auto pMemory = (int*)MapViewOfFile(hSharedMemory, FILE_MAP_ALL_ACCESS, NULL, NULL, size);

  for (int i = 0; i < 10; i++)
  {
    cout << *pMemory << endl;
    Sleep(1000);
  }

  UnmapViewOfFile(pMemory);
  CloseHandle(hSharedMemory);
}

Ⅲ. カーネルモードについて

カーネルモードとユーザーモードからアクセス可能な領域を作成するには名前を工夫する必要があります。
カーネルモードはそのままで問題ありませんが、ユーザーモードの名前を

auto name = "Global\\hoge";

とする必要があります。
また、場合によっては実行するユーザーをSYSTEMまで引き上げる必要があります。

参考
http://nahitafu.cocolog-nifty.com/nahitafu/2013/03/expartan-6twind.html

Ⅳ. 実行結果

f:id:kagasu:20170503003512g:plain