目次
2) 共有メモリマッピング (アタッチ): shmat 関数
3) 共有メモリマッピングの切り離し(detach):shmdt関数
1. 共有メモリの概要
共有メモリを使用すると、2 つ以上のプロセスが特定の記憶領域を共有できます。
共有メモリの特徴:
1) 共有メモリは、プロセス間でデータを共有する最も速い方法です。
プロセスが共有メモリ領域にデータを書き込むと、このメモリ領域を共有するすべてのプロセスはその内容をすぐに確認できます。
2) 共有メモリを使用する場合に注意すべきことは、複数のプロセス間で同一の記憶領域へのアクセスが相互排他されることです。
プロセスが共有メモリ領域にデータを書き込んでいる場合、他のプロセスはこの操作が完了するまでデータの読み取りまたは書き込みを行うべきではありません。
共有メモリの図:
共有メモリは最も効率的なプロセス間通信方法です。その理由は、プロセスが物理メモリ上で直接動作し、物理アドレスをユーザー プロセスにマップするためです。したがって、そのアドレスに対する操作が実行される限り、物理アドレスは直営で運営されています。
2. 共有メモリの操作
ubuntu12.04 の共有メモリの制限は次のとおりです。
- 共有メモリの最小バイト数: 1
- 共有ストレージ領域の最大バイト数: 32M
- 最大共有メモリ領域数:4096
- 各プロセスがマッピングできる共有ストレージ領域の最大数: 4096
シェルコマンドを使用して共有メモリを操作します。
共有メモリを表示: ipcs -m
共有メモリを削除します: ipcrm -m shmid
1) 共有ストレージ識別子の取得:shmget関数
shmget関数:
#include<sys/ipc.h>
#include<sys/shm.h>
int shmget(key_t キー、size_t サイズ、int shmflg);
機能: 共有メモリの作成
パラメータ:
key: キー値。一意のキー値により一意の共有メモリが決まります。
size: 作成される共有メモリのサイズ
shmflg: 共有メモリのアクセス許可
通常は IPC_CREAT | 0777
戻り値:
成功: 共有メモリのID
失敗: -1
コード例:
#include<sys/ipc.h>
#include<sys/shm.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
printf("shmid = %d\n", shmid);
system("ipcs -m");
return 0;
}
実行のスクリーンショット:
2) 共有メモリマッピング (アタッチ): shmat 関数
shmat関数:
#include<sys/types.h>
#include<sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
機能: 共有メモリをマップする
パラメータ:
shmid: 共有メモリのID
shmaddr: マップされたアドレス。システムによる自動割り当てのために NULL に設定されます。
shmflg: フラグビット
0: 共有メモリには読み取りおよび書き込み権限があります
SHM_RDONLY: 読み取り専用
戻り値:
成功: マップされたアドレス
失敗: -1
3) 共有メモリマッピングの切り離し(detach):shmdt関数
shmdt関数:
#include<sys/types.h>
#include<sys/shm.h>
int shmdt(const void *shmaddr);
関数:
共有メモリのマップを解除する
パラメータ:
shmaddr: マップされたアドレス、shmat の戻り値
戻り値:
成功: 0
失敗: -1
共有メモリのマッピングとマッピング解除のコード例:
write.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
int main()
{
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
char* text;
if ((text = shmat(shmid, NULL, 0)) == (void*)-1)
{
perror("fail to shmat");
exit(1);
}
//写入
strcpy(text, "hello world");
if (shmdt(text) == -1)
{
perror("fail to text");
exit(1);
}
system("ipcs -m");
return 0;
}
read.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
int main()
{
//创建共享内存
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
// system("ipcs -m");
//映射
char* text;
if ((text = shmat(shmid, NULL, 0)) == (void*)-1)
{
perror("fail to shmat");
exit(1);
}
printf("text = %s\n", text);
//解除映射
if (shmdt(text) == -1)
{
perror("fail to shmdt");
exit;
}
system("ipcs -m");
return 0;
}
実行のスクリーンショット:
4) 共有メモリ制御:shmctl関数
shmctl関数:
#include<sys/ipc.h>
#include<sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
関数:
共有メモリのプロパティを設定または取得する
パラメータ:
shmid: 共有メモリのID
cmd: 操作を実行するコマンド
IPC_STAT 共有メモリの属性を取得します
IPC_SET は共有メモリのプロパティを設定します
IPC_RMID 共有メモリの削除
shmid_ds: 共有メモリの属性構造体
戻り値:
成功: 0
失敗: -1
コード例:
#include<stdlib.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main()
{
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
printf("shmid = %d\n", shmid);
//删除共享内存
if (shmctl(shmid, IPC_RMID, NULL) == -1)
{
perror("fial to shmid");
exit(1);
}
system("ipcs -m");
return 0;
}
実行のスクリーンショット:
要約:
効率的なプロセス間通信メカニズムとして、共有メモリは、その独自の利点によりマルチプロセス環境で重要な役割を果たします。複数のプロセスが同じメモリ領域に直接アクセスできるため、データの高速な共有と交換が実現し、システム パフォーマンスが大幅に向上します。ただし、これにはデータの同期と同時実行性の制御という課題も伴います。これらの問題を解決するには、ロック、セマフォ、その他の同期テクノロジを組み合わせる必要があります。
全体として、共有メモリは強力で柔軟なツールですが、プログラムの正確さと安定性を確保するには、慎重かつ効果的に使用する必要があります。