今天我为大家讲的是进程间通信的第二种方法——共享内存。首先我们得理解一下什么是共享内存以及共享内存通信的原理。
共享内存其实就是os在内存上面开辟的一段空间,让不同的进程通过虚拟地址进程空间一起看到这同一块内存,以下是共享内存原理示意图:
参数key是内核层标定共享内存唯一性的,因为os创建了许多共享内存,为了能让不同的进程找到同一个共享内存,就用key来标识。因为有很多的共享内存需要被管理,所以os也是采用了先描述后组织的方法,通过数据结构(数组)把共享内存管理起来。所以该函数的返回值就是用户层标识共享内存的,相当于文件描述符。参数size创建共享内存的大小。参数shmflg是创建模式:
IPC_CREAT:如果共享内存不存在就创建,存在就获取共享内存。
IPC_EXCL:1.它不能够被单独使用。2.如果不存在,创建之。如果不存在,就返回报错。
所以IPC_EXCL能够保证创建出来的共享内存是新创建的!!
该函数的返回值:
key是为了标识共享内存唯一性的,所以在调用shmget系统调用的时候,需要将key传进去。其实可以告诉大家的是共享内存的内核数据结构里面就存有了可key,所以说key相当于共享内存的一种属性。以下是创建key的函数:
它的返回值:
共享内存创建好了并且两个进程都找到了同一块时,就需要将共享内存的起始地址写到进程的虚拟地址空间里面。
它的返回值:
如果成功了,返回的是共享内存的起始地址,如果失败了返回-1.
int shmdt(const void *shmaddr);
接口很简单,只需要将共享内存的起始地址填入就行。
ipcs -m
ipcrm -m + shmid
功能:用于控制共享内存原型int shmctl(int shmid, int cmd, struct shmid_ds *buf);参数shmid: 由 shmget 返回的共享内存标识码cmd: 将要采取的动作(有三个可取值)buf: 指向一个保存着共享内存的模式状态和访问权限的数据结构返回值:成功返回 0 ;失败返回 -1
了解完了上面所有函数接口,现在我们实现一个用共享内存实现进程间通信的代码:
com.hpp:
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define PATH_NAME "/tmp"
#define PROJ_ID 0X123
#define MAX_SIZE 4096
key_t getkey()
{
key_t key =ftok(PATH_NAME,PROJ_ID);
if(key ==-1)
{
cerr<<"getkey:"<
client.cc:
#include "com.hpp"
int main()
{
//创建和服务端相同的key值
key_t key =getkey();
//获取共享内存
int shmid =getShm(key);
printf("shmid: %d\n", shmid);
//将客户端和进程挂接起来
char* start =(char*)AttachShm(shmid);
cout<<"client 挂接成功 address: "<0)
{
buffer[strlen(buffer)-1]=0;
}
int cnt =1;
char buffer1[1024];
snprintf(buffer1,sizeof(buffer1),"我是客户端,我正在给你发消息[%d][%d]:%s",getpid(),cnt++,buffer);
memcpy(start,buffer1,strlen(buffer1));
}
//客户端解除挂接
DetachShm(start);
return 0;
}
server.cc:
#include "com.hpp"
int main()
{
//获取一个key
key_t key =getkey();
//创建共享内存
int shmid =createShm(key);
//将进程和共享内存进行挂接
char* start =(char*)AttachShm(shmid);
printf("server 挂接成功 ,address: %p",start);
//服务端读取数据。
while(true)
{
cout<<"client say: "<
最后我们来谈一谈共享内存的优缺点:
优先:
共享内存是进程间通信最快的一种方式,大大减少了拷贝。
缺点:
不给我进行同步与互斥的操作,对数据没有做任何保护。
共享内存相关知识就全部介绍清楚了,感谢大家多多支持!!