共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运⾏效率较低⽽设计的。往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。共享内存效率高,因为不像管道以及消息队列一样,读写时进行拷贝两次,而共享内存直接进行内存读写,不需要进行拷贝。共享内存申请的空间内存在堆栈之间。生命周期为随内核。
32位平台下一个进程认为自己的地址空间为4G,0~3G为用户区,3~4G为内核区。
在验证共享内存中我们会涉及到一些函数,下面对这些函数进行一一解释:
1、申请共享内存——shmget()函数
函数原型:int shmget(key_t key,size_t size,int shmflg);
第一个参数,程序需要提供一个参数key,有效的为共享内存段命名,key_t key=ftok(PATHNAME,PROJ_ID);
第二个参数:申请共享内存的大小,以字节为单位。(一般是4096的整数倍)
第三个参数:权限标志,IPC_CREAT|IPC_EXCL:若共享内存存在便出错返回,若不存在则创建之,IPC_CREAT:若共享内存存在便打开返回,若不存在则创建之。
返回值:返回用户可使用的共享内存标志符。
2、释放共享内存——shmctl()函数
函数原型:int shmctl(int shmid,int cmd,struct shmid_ds *buf);
第一个参数:shmget函数返回的共享内存标识符
第二个参数:要使用的操作,此处为IPC_RMID,表示删除。
第三个参数:buf对应的结构指针:
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
3、将共享内存挂接到进程的地址空间——shmat()函数
函数原型:void* shmat(int shmid,const void* shmaddr,int shmflg)
第二个参数:一般为空。
第三个参数:一般为0。
4、去关联——shmdt()函数
函数原型:int shmdt(const void* shmaddr);
参数: shmat()函数的返回值。
源码验证:
comm.h:
#ifndef _COMM_H_
#define _COMM_H_
#include<stdio.h>
#include<unistd.h>
#include<error.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#define PATHNAME "."
#define PROJ_ID 0x666
//创建共享内存
int create_shm(size_t size);
int comm_shm(size_t size,int shm_flag);
//销毁
int destroy_shm(int shmid);
//获取
int get_shm();
#endif
comm.c:
#include"comm.h"
int comm_shm(size_t size,int shm_flag)
{
key_t key=ftok(PATHNAME,PROJ_ID);
if(key<0)
{
perror("ftok");
return -1;
}
int shmid=shmget(key,size,shm_flag);
if(shmid<0)
{
perror("shmget");
return -2;
}
return shmid;
}
int create_shm(size_t 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,IPC_RMID,NULL)<0)
{
perror("shmctl");
return -1;
}
return 0;
}
server.c:
#include"comm.h"
int main()
{
int shmid=create_shm(4096);
char *buf=shmat(shmid,NULL,0);
int count=0;
while(count<4096)
{
buf[count]='A'+count%26;
count++;
sleep(3);
buf[count]=0;
}
shmdt(buf);
destroy_shm(shmid);
return 0;
}
client.c:
#include"comm.h"
int main()
{
int shmid=get_shm();
char* buf=shmat(shmid,NULL,0);
while(1)
{
printf("%s\n",buf);
sleep(3);
}
shmdt(buf);
return 0;
}