共有メモリ
1.共有メモリの概要
共有メモリは、プロセスが負のデータなしでメモリを直接読み書きできるため、プロセス間通信の最も効率的な方法の1つです。複数のプロセス間で情報を交換するために、カーネルは、アクセスする必要のあるプロセスが自身のプライベートスペースアドレスにマップできるメモリ領域を確保しています。複数のプロセスはメモリのセグメントを共有するため、ミューテックスやセマフォなどの同期メカニズムに依存する必要もあります。
2.共有メモリプログラミング
2.1プログラミング手順
共有メモリの実装は、次の2つのステップに分かれています。
- 共有メモリを作成します。つまり、メモリから共有メモリ領域を取得し、shmget()関数を使用します
- 共有メモリのマッピング、つまり作成された共有メモリを特定のプロセス空間にマップするには、
これまでにshmat()関数を使用してこの共有メモリを使用します。バッファリングされていないI / O読み取りおよび書き込みコマンドを使用して実行できます。オペレーティング。メモリマッピングを元に戻す操作もあります。関数はshmdt()です。
2.2機能紹介
shmget()は共有メモリ関数を作成します
/*****shmget()函数*****/
函数原型:int shmget(key_t key, int size, int shmflg)
传 入 值:key 共享内存的键值,多个进程可通过它访问同一个共享内存。IPC_PRIVATE用于创建私有共享内存
size 共享内存区大小
semflg 同 open() 函数的权限位
返 回 值:成功:返回共享内存标识符;
失败:返回-1
shmat()マッピング共有メモリ関数
/*****shmat()函数*****/
函数原型:int shmat(int shmid, const void *shmaddr, int shmflg)
传 入 值:shmid 要映射的共享内存区标识符
shmaddr 将共享内存映射到指定地址(若为0表示系统自动分配地址并把该段共享内存映射到调用进程的地址空间)
semflg 默认为0表示共享内存可读写;SHM_RDONLY表示共享内存只读
返 回 值:成功:被映射的段地址;
失败:返回-1
shmdt()メモリマッピング関数を元に戻す
/*****shmdt()函数*****/
函数原型:int shmdt(const void *shmaddr)
传 入 值:shmaddr 被映射的共享内存段地址
返 回 值:成功:返回0;
失败:返回-1
2.3関数の例
/*****shmem.c*****/
//省略头文件
#define BUFFER_SIZE 2048
int main(){
pid_t pid;
int shmid,
char *shm_addr;
char flag[] = "WROTE";
char *buff;
if((shmid = shmget(IPC_PRIVATE,BUFFER_SIZE,0666)) < 0){
//创建共享内存
perror("shmget");
exit(1);
}
else
printf("Creat shared-memory: %d\n",shmid);
system("ipcs -m"); //使用了system()函数调用shell命令“ipcs”,ipcs命令用于报告进程间通讯机制状态
pid = fork();
if(pid == -1){
perror("fork");
exit(1);
}
else if(pid == 0){
//子进程
if((shm_addr = shmat(shmid,0,0)) == (void*)-1){
//映射共享内存
perror("Child:shmat");
exit(1);
}
else{
printf("Child: Attach shared-memory: %p\n",shm_addr);
}
system("ipcs -m");
while(strncmp(shm_addr, flag, strlen(flag))){
printf("Child: Wait for enable data...\n");
sleep(5);
}
strcpy(buff, shm_addr + strlen(flag));
printf("Child: Shared-memory: %s\n",buff);
if((shmdt(shm_addr)) < 0){
//解除共享内存映射
perror("shmdt");
exit(1);
}
else{
printf("Child: Deattach shared-memory\n");
}
system("ipcs -m");
if((shmctl(shmid, IPC_RMID, NULL)) == -1){
//删除共享内存
perror("Child: shmctl(IPC_RMID)\n");
exit(1);
}
else{
printf("Delete shared-memory\n");
}
system("ipcs -m");
}
else{
//父进程
if((shm_addr = shmat(shmid,0,0)) == (void*)-1){
perror("Parent:shmat");
exit(1);
}
else{
printf("Parent: Attach shared-memory: %p\n",shm_addr);
}
sleep(1);
printf("\nInput some string:\n");
fgets(buff,BUFFER_SIZE,stdin);
strncpy(shm_addr + strlen(flag), buff, strlen(buff));
strncpy(shm_addr, flag, strlen(flag));
if((shmdt(shm_addr)) < 0){
perror("Parent shmdt");
exit(1);
}
else{
printf("Parent: Deattach shared-memory\n");
}
system("ipcs -m");
waitpid(pid, NULL, 0);
printf("Finished\n");
}
exit(0);
}