在system V IPC裏面,共享內存是所有進程間通信速度最快的。因爲在消息隊列裏面,在消息傳遞的時候需要進行兩次拷貝(將數據拷貝到隊列節點裏面,從隊列節點裏面拷貝到內存)。
基本原理:
注:進程間通訊的本質就是將不同的進程看到同一塊地址空間。但是在頁表的映射下,不同的進程所佔有的實際地址空間是不同的,所以在不同的進程裏面數據是相對獨立的。但是要是有一塊不同進程都可以訪問的空間,那麼就可以實現進程間通訊。這裏的共享內存就是不同進程都可以進行訪問的內存。
共享內存的缺點:共享內存沒有同步和互斥機制,但是可以銅價信號量的方法實現加鎖。
int shmget(key_t key,size_t size,int shmflag); //創建共享內存
key:共享內存的名稱編號
size:共享內存的大小
shmflag:模式標誌位(IPC_CREAT 、IPC_EXCL);
注:開闢的size通常爲一塊的整數倍(n*4K),但是用戶只能使用自己所開闢的大小內存
模式標誌位裏面,當同時使用IPC_CREAT|IPC_EXCL時候,當不存在共享內存的時候創建,當存在的時候報錯,單獨使用IPC_CREAT的時候不存在的時候創建,存在時候返回,單獨使用IPC_EXCL無任何意義。
void* shmat(int shmid,const void * shmadd,int fshmlag);//將共享內存連接到進程地址空間
shmid:共享內存編號
shmadd:指定連接地址
shmflag:模式標誌位(SHM_RND、SHM_RDONLY)
int shmdt(const void * addr);//取消共享內存連接
int shmctl(int shmid,int cmd,struct shmid_ds *buf);//控制共享內存
cmd:需要採取的動作
注:IPC_RMID:刪除共享內存
實例:實現不同進程的通信
comm.c
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#define PATHNAME "/tmp"
#define PROJE_ID 0x6666
static int commshm(int flag){
int _key = ftok(PATHNAME,PROJE_ID);
int shmid;
if(_key < 0){
perror("fyok");
return -1;
}
shmid = shmget(_key,4096,flag);
if(shmid < 0){
perror("shmget");
return -2;
}
return shmid;
}
int Greatshmid(){
return commshm(IPC_CREAT|IPC_EXCL|0666);
}
int Getshmid(){
return commshm(IPC_CREAT);
}
int Destoryshm(int shmid){
if(shmctl(shmid,IPC_RMID,NULL) < 0){
perror("shmctl");
return -1;
}
return 0;
}
#endif
comm.h
#ifndef _COMM_H__
#define _COMM_H__
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#define PATHNAME "."
#define PROJE_ID 0x12345
int commshm(int flag);
int Greatshmid();
int Getshmid();
int Destoryshm(int shmid);
#endif
server.c
#include"comm.h"
int main(){
int shmid = Greatshmid();
int i = 100;
char* addr = shmat(shmid,NULL,0);
if(NULL == addr){
perror("shmst");
return -1;
}
while(i--){
printf("client is say:%s\n",addr);
sleep(1);
}
sleep(1);
shmdt(addr);
Destoryshm(shmid);
return 0;
}
client.c
nclude"comm.h"
int main(){
int shmid = Getshmid();
int i = 0;
char* addr = shmat(shmid,NULL,0);
if(NULL == addr){
perror("shmat");
return -1;
}
while(i < 10){
addr[i] = 'A'+i;
i++;
addr[i] = 0;
sleep(1);
}
sleep(1);
shmdt(addr);
Destoryshm(shmid);
return 0;
}