3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

boost::interprocessのshared_memory_objectとmapped_regionを使ってプロセス間でメモリを共有する

Posted at

boost::interprocessを使用したプロセス間のメモリ共有

C++のオープンソースライブラリ、boostを使って共有メモリにデータを書き込んで、プロセス間でデータを共有する方法を学んだので、忘備録を兼ねてサンプルプログラムを書いてみました。

まずは、共有メモリ上にデータを書き込む親プロセスのコードです。

shm_parent.cpp
#include <iostream>
#include <string>
#include <unistd.h>

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>

const std::string childName = "shm_child";      // 子プロセスの実行ファイル名
const std::string shmObjName = "shm_sample";    // 共有メモリオブジェクトの名前
const std::string writeString = "Hello,world."; // 共有メモリに書き込む文字列

void createChildProcess();

int main()
{
  int status;
  pid_t child;

  using namespace boost::interprocess;
  // 共有メモリオブジェクトを作成(書き込み可)
  shared_memory_object shm(create_only, shmObjName.c_str(), read_write);
  // 共有メモリオブジェクトの領域を確保
  shm.truncate(writeString.size());

  // 共有メモリオブジェクトをmapped_regionにマッピング
  mapped_region map(shm, read_write);
  // 共有メモリにアクセスするポインタを取得
  char* shmPtr = static_cast<char*>(map.get_address());
  // 共有メモリへの書き込み
  memcpy(shmPtr, writeString.c_str(), writeString.size());

  if ((child = fork()) < 0)
  {
    std::cerr << "failed to fork child process.\n";
    return 1;
  }

  if (child == 0)
  {
    // 子プロセスを起動
    createChildProcess();
  }
  else
  {
    // 子プロセスの終了を待つ
    if (wait(&status) < 0)
    {
      std::cerr << "wait child process error.\n";
      return 1;
    }
    // 共有メモリオブジェクトを削除
    shared_memory_object::remove(shmObjName.c_str());
  }

  return 0;
}

void createChildProcess()
{
  execve(childName.c_str(), nullptr, nullptr);
}

共有メモリへのデータの書き込みは、以下の5ステップで行います。

###shared_memory_objectインスタンスの作成

using namespace boost::interprocess;
shared_memory_object shm(create_only, shmObjName.c_str(), read_write);

shared_memory_objectのコンストラクタには、以下の3つの引数を渡します。
####1.作成モード
共有メモリオブジェクトを作成する際の挙動を指定します。
#####create_only
メモリファイルを新規作成します。すでに同名のファイルが存在する場合には、例外が送出されます。
#####open_or_create
メモリファイルが存在する場合にはそれを読み込み、存在しなければ新規作成します。
#####open_only
メモリファイルの読み込みのみを行います。ファイルが存在しない場合は、例外が送出されます。

####2.共有メモリファイル名
作成、または読み込みを行うメモリファイルの名前を指定します。

####3.読み込み/書き込みモード
読み込み/書き込みモードのを指定します。指定できるのは、read_writeまたはread_onlyの2つです。

###mapped_regionインスタンスの作成

mapped_region map(shm, read_write);

mapped_regionのコンストラクタには、shared_memory_objectと読み込み/書き込みモードの2つを指定します。

###共有メモリへのポインタを取得

char* shmPtr = static_cast<char*>(map.get_address());

mapped_regionのget_address()関数を呼び、共有メモリへのポインタを取得します。
void型のポインタが返されるので、適切な方にキャストします。
今回は文字列を書き込むので、char
型にstatic_castでキャストしておきます。

###共有メモリへのポインタを取得

memcpy(shmPtr, writeString.c_str(), writeString.size());

最後に、memcpyなどの関数でデータをポインタに書き込みます。

次に、子プロセス側のコードです。

shm_child.cpp
#include <iostream>

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>

const std::string shmObjName = "shm_sample"; // 共有メモリオブジェクトの名前

int main(int argc, char* argv[])
{
  using namespace boost::interprocess;
  // 共有メモリオブジェクトを読み込み(読み込みのみ)
  shared_memory_object shm(open_only, shmObjName.c_str(), read_only);

  // 共有メモリオブジェクトをmapped_regionにマッピング
  mapped_region map(shm, read_only);

  // 共有メモリにアクセスするポインタを取得
  char* shmPtr = static_cast<char*>(map.get_address());

  // 読み込んだ文字列(Hello,world.)を表示
  std::cout << shmPtr << std::endl;

  return 0;
}

基本的な流れは書き込み側とほとんど変わりません。
共有メモリからデータの読み込みを行うので、モードにはopen_only, read_onlyを指定しておきます。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?