共享内存概念
共享内存指的是,在多处理器的计算机系统中,可以被不同的CPU访问大量内存。由于多个CPU需要快速访问存储器,所以必须对存储器进行缓存。在缓存中的数据被更新后,其他处理器也可能要进行读取,共享内存就需要立即更新,否则不同的处理器将读取到不同的数据。共享内存是Unix、Linux下多进程通信的一种方式之一,这种方法通常用于一个程序的多进程间通信。实际上多个进程可以通过共享内存来进行通信
有关函数接口
与共享内存有关的接口有四个:shmget,shmat,shmdt,shmctl
头文件<sys/shm.h>
<sys/types.h>
<sys/ipc.h>
进行共享内存的获取
int shmget(key_t key, size_t size, int shmflg)
参数
size 以页表为基本单位,是4k的整数倍(4096);
IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共
内存的标识符
将进程挂载到共享内存
void *shmat(int shmid, const void *shmaddr, int shmflg)
参数
shmaddr指定共享内存出现在进程内存地址的什么位置
将共享内存上的进程删除
int shmdt(const void *shmaddr)
shmaddr:连接的共享内存的地址
删除共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
参数
cmd为IPC_RMID销毁共享内存
buf共享内存管理结构体
代码实现共享内存
comm.h
#ifndef __SHM_H__
#define __SHM_H__
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/wait.h>
#include<sys/shm.h>
#define PATHNAME "."
#define PROJ_ID 0x666
int CreatShm(int size);//创建共享内存
int GetShm(int size);//获取已有的共享内存
char* AtShm(int shmid);//将进程号为 shmid 的进程 挂到共享内存上
int DtShm(char* addr);//将指向addr的共享内存上的进程移除
int Destroy(int shmid);//释放共享内存
#endif
comm.c
#include"comm.h"
//创建共享内存和获取共享内存的公共代码
static int commShm(int flag, int size)
{
key_t _key = ftok(PATHNAME, PROJ_ID);
if(_key < 0)
{
perror("ftok");
return -1;
}
int shmid = shmget(_key , size, flag);
if(shmid < 0)
{
perror("shmget");
return -2;
}
return shmid;
}
//创建共享内存
int CreatShm(int size)
{
return commShm(IPC_CREAT|IPC_EXCL|0666,size);
}
//获取已存在的共享内存
int GetShm(int size)
{
return commShm(IPC_CREAT,size);
}
//将进程号为size的进程挂到共享内存中
char* AtShm(int shmid)
{
//void* shmat(int shmid, const void* shmaddr, int shmflg);
return (char*)shmat(shmid, NULL,0);
}
//将共享内存的进程移除
int DtShm(char* addr)
{
//int shmdt(const void* shmaddr);
return shmdt(addr);
}
//销毁共享内存
int DestroyShm(int shmid)
{
//int shmctl(int shmid,int cmd,struct shmid_ds *buf);
if(shmctl((shmid),IPC_RMID,NULL)<0)
{
perror("shmctl");
return -1;
}
return 0;
}
client.c
#include"comm.h"
int main()
{
int shmid = GetShm(4096);//获取共享内存
char* addr = AtShm(shmid);//将进程挂载到共享内存
if(addr == NULL)//检测挂载是否成功
{
printf("addr == NULL\n");
}
int i = 0;
while(i < 4095)
{
addr[i] = 'a';//每次多写入一个a
addr[i+1] = '\0';//
sleep(1);//休眠1秒
i++;
}
DtShm(addr);//将进程从共享内存上移除
DestroyShm(shmid);//销毁共享内存
return 0;
}
server.c
#include"comm.h"
int main()
{
int shmid = CreatShm(4096);//创建共享内存
char* addr = AtShm(shmid);//挂载到共享内存
if(addr == NULL)
{
printf("NULL\n");
}
while(1)
{
sleep(1);
printf("%s\n",addr);
}
DtShm(addr);//将共享内存上的进程移除
DestroyShm(shmid);//删除共享内存
return 0;
}
makefile文件
.PHONY:all
all:server client
server:server.c comm.c
gcc -o $@ $^
client:client.c comm.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f server client
运行结果
共享内存的特点
1、共享内存是进程间通信最快的
2、共享内存的生命周期是随内核的
3、共享内存是属于SystemV通信的