共享内存原理
特点
- 相比管道通信,在读写数据的时候不用切内核态,使通信效率提升
- 相比命名管道,命名管道是内核管理的缓冲区队列,而共享内存不是队列结构
- 属于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 }
网友评论