目录
一、前言
二、什么是共享内存
三、共享内存的创建及使用
1、shmget()函数
2、shmat()函数
3、shmdt()函数
四、使用共享内存实现进程间通信
1、准备一个写端
2、准备一个读端
3、测试结果
进程间通信(IPC,InterProcess Communication) 是指在不同进程之间传播或交换信息,现在linux使用的进程间通信方式有:(1)管道(pipe)和命名管道(FIFO) (2)信号(signal) (3)消息队列 (4)共享内存 (5)信号量 (6)套接字(socket)。
之前介绍了信号、管道,今天我们来学习一下共享内存是如何进行进程间的通信。
共享内存是由IPC为一个进程创建的一个特殊的地址范围,它将出现在进程的地址空间中,其他进程可以把同一段共享内存段“连接到”它们自己的地址空间里去。如上图所示。
注:
之前使用的命名管道FIFO最大传输量为65535字节,而且用到的 fifo“文件”容易被用户误删,这样就会导致进程间的通信发生错误,共享内存允许两个不相关的进程去访问同一部分逻辑内存,效率极高,所以接下来介绍一下共享内存如何用代码创建并且去使用它。
#include
#include函数原型:
int shmget(key_t key, size_t size, int shmflg);
参数:
key:(非0整数),它有效地为共享内存段命名
size:需要共享的内存量
shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
返回值:
如果共享内存创建成功,返回一个非负整数,即该段共享内存的标识码;
如果失败,则返回 -1 。
示例:
#include
#include
#include
#include
using namespace std;
int main()
{
int shmid = 0;
//不存在则创建共享内存,存在则获取
shmid = shmget((key_t)1001, 10086, IPC_CREAT | 0777);
if (shmid < 0)
{
perror("shmget error");
}
else
{
cout << "创建共享内存成功" << endl;
}
return 0;
}
Ipcrm -a 全部删除 除了系统原本root创建的内存段
通过 ipcrm 命令将上一步创建的共享内存删掉
#include
#include函数原型:
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数:
shmid:通过shmget()函数返回的共享内存标识
shmaddr:把共享内存连接到当前进程去的时候准备放置它的那个地址
shmflg:可以指定为0,
返回值:
成功:返回一个指针,指针指向共享内存的第一个字节,也就是共享内存的首地址
失败:则返回 -1 。
#include
#include函数原型:
int shmdt(const void *shmaddr);
参数:
shmaddr:由shmat()函数返回的地址指针
返回值:
成功:返回 0 ,
失败:返回 -1 。
注:
:使用shmdt()函数脱离共享内存并不等于删除它,只是当前进程不能再继续访问它而已
下面通过一个小例子来使用共享内存实现两个不相关进程间的简单通信。
#include
#include
#include
#include
#include
using namespace std;
typedef struct student
{
char id[10];
char name[10];
}STU;
int main()
{
STU stu = { "10001","admin" };
void* shamdaddr = NULL;
int shmid = 0;
//不存在则创建共享内存,存在则获取
shmid = shmget((key_t)1001, 10086, IPC_CREAT | 0777);
if (shmid < 0)
{
perror("shmget error");
}
else
{
//连接共享内存,首地址存到 shamdaddr
shamdaddr = shmat(shmid, NULL, 0);
memcpy(shamdaddr, &stu, sizeof(STU));//内存拷贝 即:将stu结构体的数据写入共享内存中
cout << "写入数据成功" << endl;
//结束连接 当前进程脱离共享内存
shmdt(shamdaddr);
}
return 0;
}
#include
#include
#include
#include
#include
using namespace std;
typedef struct student
{
char id[10];
char name[10];
}STU;
int main()
{
STU stu = { 0 };
void* shamdaddr = NULL;
int shmid = 0;
//不存在则创建共享内存,存在则获取
shmid = shmget((key_t)1001, 10086, IPC_CREAT | 0777);
if (shmid < 0)
{
perror("shmget error");
}
else
{
//连接共享内存,首地址存到 shamdaddr
shamdaddr = shmat(shmid, NULL, 0);
memcpy(&stu, shamdaddr, sizeof(stu)); //内存拷贝 即:将共享内存中的数据写入空的结构体中
cout << "获取数据成功" << endl;
cout << stu.id << endl;
cout << stu.name << endl;
//结束连接 当前进程脱离共享内存
shmdt(shamdaddr);
}
return 0;
}
两个工程的代码都差不多,区别是一个写数据,一个读数据。
共享内存段也正常创建出来,连接数为0,是因为程序运行结束了。
共享内存里的数据没有做改动会一直存在,重复读取内容是可以读取到的。
原创不易,转载请标明出处。
对您有帮助的话可以一键三连,会持续更新的(嘻嘻)。