Linux 之 IPC进程间通信(四、共享内存SHM)

1. 什么是共享内存

        1. 是一块独立于两个通信进程的内存空间,通过对这块的读写操作实现进程间通信。

        2. 优缺点

                1. 操作方便;

                2. 无大小限制;

                3. 无阻塞函数,难以实现即时接收;

2. 共享内存的操作

void* shmadr = NULL;
int shmid = shmget((key_t)1002, sizeof(STU), IPC_CREAT|0777);
shmadr = shmat(shmid, NULL, 0);//连接
memcpy(shmadr, &stu, sizeof(STU));//写入/读出
shmdt(shmadr);//断开

        1. Shmget()根据键值、大小、权限为创建新的共享内存 或 获取已有的共享内存;

        2. Shmat()连接函数,通过文件描述符返回共享内存初地址;

  • 案例:见最后

3. 消息队列SHM与共享内存MSG配合实现即时通信

  • 结合消息列表(或管道)的阻塞的特点,实现即时通讯;
  • 最好在读共享内存后清空内存块(根据实际业务);
  • 创建一个消息队列可以两端同时读写,不区分哪个端口;

 


案例

 【案例1:共享内存】

写端:

#include<iostream>
using namespace std;
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>

typedef struct student {
	char stuid[20];
	char stuname[20];
}STU;

int main()
{
	STU stu = { "00001","壹号" };
	void* shmadr = NULL;
	int shmid = shmget((key_t)1002, sizeof(STU), IPC_CREAT|0777);

	if (shmid == -1)
	{
		perror("shmid error");
	}
	else {
		shmadr = shmat(shmid, NULL, 0);//连接
		memcpy(shmadr, &stu,sizeof(STU));//写入
		cout << "写入" << stu.stuid << stu.stuname << endl;
		shmdt(shmadr);//断开
	}
	return 0;
}

读端:

int main()
{
	STU stu = { 0 };
	void* shmadr = NULL;
	int shmid = shmget((key_t)1002, sizeof(STU), IPC_CREAT | 0777);
	if (shmid == -1)
	{
		perror("shmid error");
	}
	else {
		shmadr = shmat(shmid, NULL, 0);//连接
		memcpy( &stu, shmadr,sizeof(STU));//读出
		cout << "读出" << stu.stuid << stu.stuname << endl;
		shmdt(shmadr);//断开
	}
	return 0;
}

实例2【SHM与MSG实现即时通信】

写端:

#include<iostream>
using namespace std;
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>


//实现不同的功能:
//数据会丢失,单一共享内存(目前只能这样)
//双端堵塞等待发送

typedef struct student {
	int num;
	char name[20];
	char number[20];
}STU;

typedef struct Msgbuf 
{ long mtype;  
char mtext[50]; 
}MSGBUF;


int main()
{
	int msgid = msgget((key_t)1003, IPC_CREAT | 0777);
	if (msgid == -1) {
		perror("msgget error");
	}
	else {
		cout << "消息队列创建成功" << endl;
	}
	MSGBUF buf = {0};
	buf.mtype = 1;


	void* shmaddr = NULL;
	int shmid = shmget((key_t)1002, sizeof(STU), IPC_CREAT | 0777);
	if (shmid == -1) {
		perror("shmget error");
	}
	else {
		cout << "共享内存创建成功" << endl;
	}
	
	cout << "等待收端连接……(msgrcv阻塞)" << endl;
	msgrcv(msgid, &buf, sizeof(buf), 1, 0);
	cout << "双端连接成功!\n"<<  endl;

	shmaddr = shmat(shmid, NULL, 0); //获得共享内存地址
	for (int i = 0; i < 3; i++)
	{
		int k = 0;
		cin >> k;
		sleep(1);
		STU stu = { i,"000001","壹号" };
		memcpy(shmaddr,&stu,sizeof(stu));  //写入
		cout << "写入至共享内存: " << stu.num << stu.name << stu.number << endl;
		msgsnd(msgid, &buf, sizeof(buf), 0);//发送消息队列
		cout << "已通知(发送消息队列)" << endl;
		
	}
	return 0;
}

读端:

#include<iostream>
using namespace std;
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

//实现不同的功能:
//数据会丢失,单一共享内存(目前只能这样)
//双端堵塞等待发送

typedef struct student {
	int num;
	char name[20];
	char number[20];
}STU;
typedef struct Msgbuf
{
	long mtype;
	char mtext[50];
}MSGBUF;

int main()
{

	int msgid = msgget((key_t)1003, IPC_CREAT | 0777);
	if (msgid == -1) {
		perror("msgget error");
	}
	else {
		cout << "消息队列创建成功" << endl;
	}
	MSGBUF buf = { 0 };
	buf.mtype = 1;

	void* shmaddr = NULL;
	int shmid = shmget((key_t)1002, sizeof(STU), 0);
	if (shmid == -1) {
		perror("shmget error");
	}
	else {
		cout << "共享内存创建成功" << endl;
	}

	
	msgsnd(msgid, &buf, sizeof(buf), 0);//发送消息队列
	cout << "请求发端连接" << endl;

	shmaddr = shmat(shmid, NULL, 0); //获得共享内存地址
	for (int i = 0; i < 3; i++)
	{
		STU stu = { 0 };
		cout << "等待接收(msgrcv处于阻塞状态)" << endl;
		ssize_t res =  msgrcv(msgid, &buf, sizeof(buf), 1, 0);

		cout << "已接收通知(接受消息队列)" << res <<endl;
		memcpy(&stu, shmaddr, sizeof(stu));  //读出
		cout << "读出成功: " << stu.num << stu.name << stu.number << endl;
	}





	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值