System V IPC:共享内存

共享内存原理

特点
  • 相比管道通信,在读写数据的时候不用切内核态,使通信效率提升
  • 相比命名管道,命名管道是内核管理的缓冲区队列,而共享内存不是队列结构
  • 属于System V IPC(另外两种是信号量消息队列
  • 一种IPC资源,不依赖进程是否存在
原理
  • 进程共享使用同一段物理内存
  • 具有使用权限的进程将共享内存(同一块物理内存)映射到自己地址空间(虚拟地址空间)的一部分
  • 每个共享内存有一个 shmid_ds类型的结构与之对应
struct shmid_ds
{
  uid_t shm_perm.uid;
  uid_t shm_perm.gid;
  mode_t shm_perm.mode;
  
...
}

使用到的API

  • 创建(打开)共享内存--shmget
#include <sys/shm.h>
int shmget(key_t key,size_t size,int shmflg);

参数表
key:共享内存对应键值
size:共享内存大小
shmflg:共享内存权限----IPC_CREATE(创建shm,省略则为打开)|mode(0777)
返回值
大于0:共享内存ID
-1 :出错

  • 连接共享内存--shmat
#include <sys/shm.h>
void * shmat(int shmid,void * shmaddr,int flg);

参数表
shmid:共享内存id号(shmget返回值)
shmaddr:共享内存的起始地址(常用NULL,让内核给分配)
flg:访问共享内存的方式:SHM_RDONLY(读方式)/ 0(可读可写)
返回值
大于0:共享内存起始地址
-1 :出错

  • 解脱共享内存--shmdt
    解脱后shmid_ds结构体中计数器减一(类似文件操作)
#include <sys/shm.h>
int shmdt(void * shmaddr);

参数表
shmaddr:共享内存起始地址(shmat返回值)
返回值
0:成功
-1 :出错

  • 操作(删除)共享内存--shmctl
#include <sys/shm.h>
int shmctl(int shmid,int cmd,struct shmid_ds *buf);

参数表
shmid:共享内存id号
cmd:执行的操作:如 IPC_RMID,删除共享内存
buf:cmd不同,buf不同,删除时填NULL
返回值
0:成功
-1 :出错

示例代码

写端

  1 #include <sys/shm.h>
  2 #include <unistd.h> //sleep
  3 #include <string.h> //strcpy
  4 #include <iostream> //perror
  5 using namespace std;
  6 #define SHM_KEY 98  //设定创建共享内存的键值
  7 
  8 int main()
  9 {
 10         int seg_id;     //共享内存id号
 11         char *mem_ptr = NULL;   //指向共享内存的指针
 12         
 13         seg_id = shmget(SHM_KEY,1024,IPC_CREAT|0777);//创建共享内存:键值,大小,权限
 14         if( seg_id == -1 )
 15         {
 16                 perror( "shmget" );
 17                 exit(EXIT_FAILURE);     
 18         }
 19         
 20 
 21         mem_ptr = (char*)shmat(seg_id,NULL,0);//连接共享内存
 22         if(mem_ptr == NULL)
 23         {
 24                 perror("shmat");
 25                 exit(EXIT_FAILURE);     
 26         }
 27         
 28         
 29         cout << "1" << endl;
 30         char  temp[8] = "1234567";
 31         strcpy(mem_ptr,"1234567\n");
 32 //      cout << sizeof(*mem_ptr) << endl;
 33         cout << "2" << endl;
 34         sleep(10);      //等待读端读数据
 35 
 36         shmctl(seg_id,IPC_RMID,NULL);//删除共享内存
 37         return 0;
 38 } 

读端

  1 #include <sys/shm.h> 
  2 #include <unistd.h> 
  3 #include <string.h> 
  4 #include <iostream>
  5 using namespace std;
  6 
  7 #define SHM_KEY 98
  8 
  9 int main()
 10 {
 11         int seg_id;
 12         
 13         char * mem_ptr;
 14         seg_id = shmget(SHM_KEY,00,0777);
 15         if( seg_id == -1 )
 16         {       
 17                 perror("shmget");
 18                 exit(EXIT_FAILURE);     
 19         }
 20 
 21 
 22         mem_ptr = (char*)shmat(seg_id,NULL,0);
 23         if(mem_ptr == NULL)
 24         {       
 25                 perror("shmat");
 26                 exit(EXIT_FAILURE);     
 27         }
 28         cout << mem_ptr <<endl;
 29 
 30         shmdt(mem_ptr);//共享内存解脱
 31         return 0;       
 32 } 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。