1. 共有メモリの概要:
共有メモリはプロセス間通信の最も効率的な方法であり、プロセスはデータをコピーせずにメモリを直接読み書きできます。
複数のプロセス間で情報を交換するために、カーネルは、アクセスする必要があるプロセスが独自のプライベート アドレス空間にマッピングできるメモリ領域を確保します。
プロセスはデータをコピーせずにこのメモリ領域を直接読み書きできるため、効率が大幅に向上します。
複数のプロセスがメモリのセクションを共有するため、ミューテックスやセマフォなど、ある種の同期メカニズムに依存する必要もあります。
2. 共有メモリの特徴:
2.1 共有メモリは、プロセス間でデータを共有する最も速い方法です。プロセスが共有メモリ領域にデータを書き込むと、このメモリ領域を共有するすべてのプロセスはその内容をすぐに確認できます。
2.2 共有メモリを使用する際に注意すべき点は、複数のプロセス間で特定の記憶領域へのアクセスが相互排他されることです。プロセスが共有メモリ領域にデータを書き込んでいる場合、他のプロセスはこの操作が完了するまでデータの読み取りまたは書き込みを行うべきではありません。
3. フレーム図:
4. 共有メモリ API 分析:
4.1 共有メモリを作成または取得します。
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:
创建或获取共享内存
参数:
1> key:密钥 一组16进制的地址
1>自动获取:IPC_PRIVATE:系统自动创建分配共享内存
弊端:永远都找不到同一块内存,不断创建新的共享内存,不采用
2>手动获取:
采用ftok函数
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:
手动创建或获取key
参数:
1>pathname:工程文件名(带路径)
2>proj_id :工程代号
返回值:
成功返回key
失败返回-1,并设置错误码
//只要参数不变化,总可以找到同一key
2>size:共享内存大小
3>shmflg:使用权限:
IPC_CREAT|0666
返回值:
成功返回shmid
失败返回-1,并设置错误码
ftok: 機能: カーネル内で一意の共有メモリ識別子を作成し、カーネルが一意の共有メモリ、セマフォ、またはメッセージ キューを識別できるようにします。
4.2 コントリビューション メモリ マッピング:
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:
将共享内存映射到用户空间(进程)
参数:
1>shmid:共享内存ID
2>shmaddr:你想要映射到的地方:NULL 自行寻找
3>shmflg:0 可读可写
返回值:
成功返回映射到的地址
失败返回(void *)-1,并设置错误码
4.3 アンマッピング
shmdt
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
功能:
解除映射操作
参数:
shmaddr:需要解除的地址
返回值:
成功返回0
失败返回-1,并设置错误码
4.4 共有メモリの削除
4>删除共享内存
shmctl --->共享内存操作
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:
对共享内存进行操作
PS:删除只是其中一环
参数:
1>shmid:需要操作的共享内存ID号
2>cmd:删除共享内存操作:
IPC_RMID:删除共享内存
3>buf:结构体指针:用来赋值的操作
IPC_RMID:NULL
返回值:
IPC_RMID:成功返回0
失败返回-1,并设置错误码
5. システム内の共有メモリを確認します。
ipcs -m
6. システム内の共有メモリを削除します
ipcrm -m 共享内存ID
7. 共有メモリの例:
一方の端に次のように書きます。
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main(){
//创建密钥
key_t key=ftok("pause.c",1);
if(key<0){
perror("ftok");
return -1;
}
printf("key:%#x\n",key);
//1>创建或获取共享内存
int shmid=shmget(key,200,IPC_CREAT|0666);
//int shmid=shmget(IPC_PRIVATE,200,IPC_CREAT|0666);
if(shmid<0){
perror("shmget");
return -1;
}
printf("共享内存ID号为:%d\n",shmid);
//2>将共享内存映射到用户空间
void *addr=shmat(shmid,NULL,0);
if(addr==(void *)-1){
perror("shmat");
return -1;
}
char *p=(char *)addr;//将万能指针型转化为char *
printf("进程的地址为:%p\n",p);
//3>解除映射
int ret=shmdt(addr);
if(ret<0){
perror("shmdt");
return -1;
}
//4>删除共享内存
ret=shmctl(shmid,IPC_RMID,NULL);
if(ret<0){
perror("shmctl");
return -1;
}
//通信?
//while(1){
scanf("%s",p);//此时,p为野指针,发生段错误
//}
return 0;
}
一方の端には次のように書かれています。
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main(){
//创建密钥
key_t key=ftok("pause.c",1);
if(key<0){
perror("ftok");
return -1;
}
printf("key:%#x\n",key);
//1>创建或获取共享内存
int shmid=shmget(key,200,IPC_CREAT|0666);
//int shmid=shmget(IPC_PRIVATE,200,IPC_CREAT|0666);//最好不使用
if(shmid<0){
perror("shmget");
return -1;
}
printf("共享内存ID号为:%d\n",shmid);
//2>将共享内存映射到用户空间
void *addr=shmat(shmid,NULL,0);
if(addr==(void *)-1){
perror("shmat");
return -1;
}
char *p=(char *)addr;//将万能指针型转化为char *
printf("进程的地址为:%p\n",p);
//3>通信?
while(1){//共享内存是不会阻塞的
printf("%s\n",p);
}
return 0;
要約:
共有メモリ: メモリ領域を使用して 2 つのプロセスの空間をマッピングします。2 つのプロセスはメモリを介してデータを転送し、メモリ領域に直接入力し、直接出力します。メモリ領域を操作する場合、操作が必要な場合は最も効率的です。厳密ではありませんが、エラーが発生するセグメントは比較的一般的である可能性があります。メモリ領域は直接入出力されるため、ブロックの概念はありませんが
、(1)// は利用できず、他の手段が必要です。