地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

共有メモリの生成

共有メモリとはプロセス間通信の中でも割と簡単に行える方法の一つ。SHARED MEMORY

wikipediaより

複数のプログラム間の通信手段として使う場合と、単に複製を用意する冗長さを防ぐ目的の場合などがある。共有メモリはプログラム間でデータをやりとりする効率的手段である。文脈によって、それらプログラムが単一のプロセッサ上で動作する場合と複数の異なるプロセッサ群上で動作する場合がある。単一のプログラムの内部でメモリを使って通信する場合もあり、例えばマルチスレッドが典型的だが、仮想空間をもともと共有している場合は「共有メモリ」とは呼ばない。

共有メモリの操作はsh*って感じのシステムコールが用意されていてこの辺を用いて扱っていく

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
 
int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shmid, void *shmaddr, int shmflg);
int shmdt(void *shmaddr);
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

shmget(2)は共有メモリの領域獲得に成功するとユニークな ID を返しそのIDを元にプロセス間通信を行っていく。

以下のサンプルは親プロセスと子プロセスで異なるメモリ空間を使用しつつメッセージを共有しているサンプル。

mmap(2)の引き数 prot には、メモリ保護をどのように行なうかを指定しています。

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

void* create_shared_memory(size_t size)
{
  int protection = PROT_READ | PROT_WRITE;
  int visibility = MAP_SHARED | MAP_ANONYMOUS;

  return mmap(NULL, size, protection, visibility, -1, 0);
}

int main(int argc, char ** argv) {
  char* parent_message = "hello";
  char* child_message = "goodbye";

  void* shmem = create_shared_memory(128);

  memcpy(shmem, parent_message, sizeof(parent_message));

  int pid = fork();

  if (pid == 0) {
    printf("Child read: %s", shmem);
    memcpy(shmem, child_message, sizeof(child_message));
    printf("Child wrote: %s", shmem);
  } else {
    printf("Parent read: %s", shmem);
    sleep(1);
    printf("After 1s, parent read: %s", shmem);
  }
}
  • PROT_READ|PROT_WRITE = 読み書き可能 PROT_EXECを追記することで実行可能になる
  • MAP_SHARED | MAP_ANONYMOUS = このマッピングを、このオブジェクトをマップした他の全てのプロセスと共有する。ただしどのファイルとも関連付けされない