1. 什么是共享内存?
进程A可以及时看到进程B堆内存中数据的更新。由于多个进程共享一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。有关信号量的更多内容,可以查阅我的前一篇文章:http://blog.youkuaiyun.com/sayhello_world/article/details/61422898
2. 共享内存优缺点:
优点:采用共享内存的一份好处是效率高,因为进程可以直接读写空间,不需要数据拷贝,而消息队列与管道都经过了2次拷贝,写端写的时候往队列拷贝一份,读端读的时候又拷贝了一份。
缺点:以前的进程间通信都自带同步互斥机制,但共享内存并没有,需要自己加锁。
3. 代码实现:
思想:既然进程间通信为即读即写,那么写端每秒向内存中写入一个字符,读端每秒就会多读一个字符。
申请内存:
函数:int shmget(key_t key,size_t size,int shmflg)
参数:
size:内存大小,一般为4096的整数倍。4096为一页的大小。
shmflg:IPC_CREAT,IPC_EXCL
销毁内存:
函数:intshmctl(int shmid,int cmd,struct shmid_ds * buf)
参数:
cmd:这里设置为0
buf:删除为IPC_RMID
挂接:
函数:void *shmat(int shmid,const void*shmaddr,int shmflg)
返回值:与malloc返回值相同,都是返回void*
参数:
shmaddr:挂接到指定的内存下,一般都为NULL
shmflg:为0
去挂接:
函数:int shmdt(const void *shmaddr)
代码:
comm.c
#include"comm.h"
static int comm_shm(int size,int flags)
{
key_t key = ftok(PATHNAME,PROJ_ID);
int shmid = shmget(key,size,flags);
if(shmid < 0)
{
perror("shmget\n");
return -1;
}
return shmid;
}
int creat_shm(int size)
{
return comm_shm(size,IPC_CREAT|IPC_EXCL|0666);
}
int get_shm()
{
return comm_shm(0,IPC_CREAT);
}
int destroy_shm(int shmid)
{
if(shmctl(shmid,0,IPC_RMID)<0){
perror("shmctl");
return -1;
}
return 0;
}
server.c
//向内存中写
int main()
{
int shmid = creat_shm(4096);
char *buf = shmat(shmid,NULL,0);
int count = 0;
while(count < 4096)
{
buf[count] = 'A'+count%26;
count++;
buf[count] = 0;
sleep(1);
}
shmdt(buf);
destroy_shm(shmid);
return 0;
}
client.c
//从内存中读
int main()
{
int shmid = get_shm();
char* buf = shmat(shmid,NULL,0);
while(1)
{
printf("%s\n",buf);
sleep(1);
}
shmdt(buf);
return 0;
}
最后运行时,可以用脚本代码实时监控挂接数目。
while :; do ipcs -m|grep -E 'owner|root';sleep 1;echo "###############";done