共享內(nèi)存原理
特點(diǎn)
- 相比管道通信陡厘,在讀寫(xiě)數(shù)據(jù)的時(shí)候不用切內(nèi)核態(tài)导披,使通信效率提升
- 相比命名管道舵鳞,命名管道是內(nèi)核管理的緩沖區(qū)隊(duì)列,而共享內(nèi)存不是隊(duì)列結(jié)構(gòu)
- 屬于System V IPC(另外兩種是信號(hào)量和消息隊(duì)列)
- 一種IPC資源狡孔,不依賴(lài)進(jìn)程是否存在
原理
- 進(jìn)程共享使用同一段物理內(nèi)存
- 具有使用權(quán)限的進(jìn)程將共享內(nèi)存(同一塊物理內(nèi)存)映射到自己地址空間(虛擬地址空間)的一部分
- 每個(gè)共享內(nèi)存有一個(gè) shmid_ds類(lèi)型的結(jié)構(gòu)與之對(duì)應(yīng)
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
...
}
使用到的API
- 創(chuàng)建(打開(kāi))共享內(nèi)存--shmget
#include <sys/shm.h>
int shmget(key_t key,size_t size,int shmflg);
參數(shù)表:
key:共享內(nèi)存對(duì)應(yīng)鍵值
size:共享內(nèi)存大小
shmflg:共享內(nèi)存權(quán)限----IPC_CREATE(創(chuàng)建shm懂诗,省略則為打開(kāi))|mode(0777)
返回值:
大于0:共享內(nèi)存ID
-1 :出錯(cuò)
- 連接共享內(nèi)存--shmat
#include <sys/shm.h>
void * shmat(int shmid,void * shmaddr,int flg);
參數(shù)表:
shmid:共享內(nèi)存id號(hào)(shmget返回值)
shmaddr:共享內(nèi)存的起始地址(常用NULL,讓內(nèi)核給分配)
flg:訪問(wèn)共享內(nèi)存的方式:SHM_RDONLY(讀方式)/ 0(可讀可寫(xiě))
返回值:
大于0:共享內(nèi)存起始地址
-1 :出錯(cuò)
-
解脫共享內(nèi)存--shmdt
解脫后shmid_ds結(jié)構(gòu)體中計(jì)數(shù)器減一(類(lèi)似文件操作)
#include <sys/shm.h>
int shmdt(void * shmaddr);
參數(shù)表:
shmaddr:共享內(nèi)存起始地址(shmat返回值)
返回值:
0:成功
-1 :出錯(cuò)
- 操作(刪除)共享內(nèi)存--shmctl
#include <sys/shm.h>
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
參數(shù)表:
shmid:共享內(nèi)存id號(hào)
cmd:執(zhí)行的操作:如 IPC_RMID,刪除共享內(nèi)存
buf:cmd不同苗膝,buf不同殃恒,刪除時(shí)填NULL
返回值:
0:成功
-1 :出錯(cuò)
示例代碼
寫(xiě)端
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 //設(shè)定創(chuàng)建共享內(nèi)存的鍵值
7
8 int main()
9 {
10 int seg_id; //共享內(nèi)存id號(hào)
11 char *mem_ptr = NULL; //指向共享內(nèi)存的指針
12
13 seg_id = shmget(SHM_KEY,1024,IPC_CREAT|0777);//創(chuàng)建共享內(nèi)存:鍵值,大小荚醒,權(quán)限
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);//連接共享內(nèi)存
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); //等待讀端讀數(shù)據(jù)
35
36 shmctl(seg_id,IPC_RMID,NULL);//刪除共享內(nèi)存
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);//共享內(nèi)存解脫
31 return 0;
32 }