備忘録

備忘録

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
http://kagasu.hatenablog.com/entry/2017/09/27/191922

Ⅳ. 実行結果

f:id:kagasu:20170503003512g:plain

その他

以下記事の方法でC#でも同じメモリ空間を利用できます。
https://kagasu.hatenablog.com/entry/2021/10/16/132558