c言語プログラミング基礎のIPC共有メモリ

3171 ワード

共有メモリ(Shared Memory)は最も簡単なプロセス間通信方式であり、複数のプロセスが同じメモリにアクセスでき、1つのプロセスがデータを変更した後、他のプロセスがデータの変化を見ることができる.
共有メモリはプロセス間で最も高速な通信方法です.
プロセスは同じメモリ領域を共有します.
「共有メモリへのアクセスは、プライベートメモリへのアクセスと同じくらい速い.
「システム呼び出しやカーネルエントリは必要ありません.
'不要なメモリコピーは発生しません.
カーネルは共有メモリへのアクセスを同期しないため、プログラマは自分で同期を提供する必要があります.
共有メモリの使用:
「プロセスによってメモリセグメントが割り当てられます.
「このメモリセグメントを使用するプロセスは、このメモリセグメントを接続します.
「各プロセスが共有メモリセグメントを使用した後、このメモリセグメントを分離します.
「ある場所では、このメモリセグメントを破棄するプロセスが必要です.
Linuxのメモリモデル:
「各プロセスの仮想メモリはページ(page)に分けられます.
「各プロセスは、自分のメモリアドレスから仮想メモリページへのマッピングを維持します.
「実際のデータはプロセスのメモリアドレスに存在します.
「各プロセスには独自のアドレス空間があるにもかかわらず、複数のプロセスのマッピングは同じページを指すことができる.
すべての共有メモリセグメントのサイズは、Linuxメモリページのサイズの整数倍です.
Linuxのページサイズは4 KBですが、プログラマーはgetpagesize関数を使用してこの値を取得する必要があります.
配分:shmget
「最初のパラメータは、作成するセグメントを指定する整数キーです.関係のないプロセスは、同じキーを指定することで、同じ共有メモリにアクセスできます.
‘定数IPC使用_PRIVATEは最初のパラメータとして,キーの衝突を回避できる.
「2番目のパラメータは、割り当てられたセグメントのサイズ(バイト数)です.実際に割り当てられたバイト数は、ページサイズに対する余分な部分の整数倍を捨てます.
「3番目のパラメータは、作成されたオプションを表すビットフラグです.
``IPC_CREATE:新しい共有メモリ領域を作成することを示します.
``IPC_EXCL:常に前のフラグと一緒に使用します.指定したキーの共有メモリセグメントがすでに存在する場合、このフラグは呼び出しに失敗します.このフラグが指定されていない場合、呼び出しは、このキーを使用している共有メモリセグメントを返します.
'‘モードフラグ:9 bitのフラグは、システムのファイル権限と同じフラグを使用しますが、実行フラグは無効です.これらのフラグはに定義されています.
「戻り値は、新しく作成されたメモリセグメントまたは取得されたメモリセグメントのフラグ(SHMID)です.
接続せつぞく:shmat shmat
「最初のパラメータはshmgetから得られたフラグ(SHMID)である.
「2番目のパラメータは、マッピングしたいプロセスのアドレス空間を指すポインタです.NULLを指定した場合、Linuxは使用可能なアドレスを選択します.

/* */
#include
#include
#include
#include
#include
#include

#define ARRAY_SIZE 4000
#define MALLOC_SIZE 10000
#define SHM_SIZE 10000
#define SHM_MODE 0666 //

char array[ARRAY_SIZE];

main()
{
int shmid;
char *p,*shmp;

printf("array[] from %lx to %ls
",(unsigned long)&array[0],(unsigned long)&array[ARRAY_SIZE] );
printf("stack around %lx
",(unsigned long)&shmid);

if ((p = malloc(MALLOC_SIZE)) == NULL)
printf("malloc error! errno=%d
",errno);
printf("malloced from %lx to %lx
",(unsigned long)p,(unsigned long)p+MALLOC_SIZE);

if((shmid= shmget(IPC_PRIVATE,SHM_SIZE,SHM_MODE)) < 0){
if((shmid = shmget(IPC_PRIVATE,SHM_SIZE,IPC_CREAT|SHM_MODE)) < 0)
printf("creat shmget error! error=%d
",errno);
exit(-1);
}

/*if((shmid = shmget(IPC_PRIVATE,SHM_SIZE,IPC_CREAT|SHM_MODE)) < 0)
printf("shmget error! errno=%d
",errno);*/
if((shmp = shmat(shmid,0,0)) == (void*) -1)
printf("shmat error! errno=%d
",errno);
printf("shared memory attached from %lx to %lx
",(unsigned long)shmp,(unsigned long)shmp+SHM_SIZE);

if(shmctl(shmid,IPC_RMID,0) < 0)
printf("shmctl error! errno=%d
",errno);

shmdt(shmp);
exit(0);
}