C/C++ linux 实现共享内存(share memory)的读写操作【代码实例】
什么是共享内存? 简单来说,共享内存就是允许两个或多个进程共享一定的存储区。
·
文档声明:
以下资料均属于本人在学习过程中产出的学习笔记,如果错误或者遗漏之处,请多多指正。并且该文档在后期会随着学习的深入不断补充完善。感谢各位的参考查看。
笔记资料仅供学习交流使用,转载请标明出处,谢谢配合。
如果存在相关知识点的遗漏,可以在评论区留言,看到后将在第一时间更新。
作者:Aliven888
什么是共享内存
简单来说,共享内存就是允许两个或多个进程共享一定的存储区。
使用共享内存的优缺点
1、优点:我们可以看到使用共享内存进行进程间的通信真的是非常方便,而且函数的接口也简单,数据的共享还使进程间的数据不用传送,而是直接访问内存,也加快了程序的效率。同时,它也不像匿名管道那样要求通信的进程有一定的父子关系。
2、缺点:共享内存没有提供同步的机制,这使得我们在使用共享内存进行进程间通信时,往往要借助其他的手段来进行进程间的同步工作。
与共享内存有关的函数
在linux系统中,使用共享内存需要引入以下几个头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
// 创建共享内存
int shmget(key_t key, size_t size, int shmflg);
// 参数
key :长整型(唯一非零),系统建立IPC通讯 ( 消息队列、 信号量和 共享内存) 时必须指定一个ID值。
通常情况下,该id值通过ftok函数得到,由内核变成标识符,要想让两个进程看到同一个信号集,只需设置key值不变就可以。
size:指定共享内存的大小,它的值一般为一页大小的整数倍(未到一页,操作系统向上对齐到一页,
但是用户实际能使用只有自己所申请的大小)。
shmflg:是一组标志,创建一个新的共享内存,将shmflg 设置了IPC_CREAT标志后,共享内存存在就打开。
而IPC_CREAT | IPC_EXCL则可以创建一个新的,唯一的共享内存,如果共享内存已存在,返回一个错误。
一般我们会还或上一个文件权限
//返回值:
成功返回共享内存的ID, 出错返回-1
// 操作共享内存
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
// 参数
shm_id :是shmget函数返回的共享内存标识符。
cmd :要采取的操作,它可以取下面的三个值 :
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值。
IPC_RMID:删除共享内存段。
buf :一个结构指针,它指向共享内存模式和访问权限的结构。
shmid_ds结构至少包括以下成员
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
//返回值:
成功返回0,出错返回-1
// 挂接操作 —— 创建共享存储段之后,将进程连接到它的地址空间
void *shmat(int shm_id, const void *shm_addr, int shmflg);
//参数:
shm_id :是由shmget函数返回的共享内存标识。
shm_addr :指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。
shm_flg :是一组标志位,通常为 0。
//返回值:
成功返回指向共享存储段的指针,出错返回-1
//分离操作
//该操作不从系统中删除标识符和其数据结构,要显示调用shmctl(带命令IPC_RMID)才能删除它
int shmdt(const void *shmaddr);
//参数:
addr :参数是以前调用shmat时的返回值
//返回值 :
成功返回0,出错返回-1
代码实例:
shmDatadef 数据文件
//shmDatadef.h
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <iostream>
using namespace std;
#define SHARE_MEMORY_BUFFER_LEN 1024
struct stuShareMemory{
int iSignal;
char chBuffer[SHARE_MEMORY_BUFFER_LEN];
stuShareMemory(){
iSignal = 0;
memset(chBuffer,0,SHARE_MEMORY_BUFFER_LEN);
}
};
writeShareMemory 文件:
//writeShareMemory.cpp
#include "shmDatadef.h"
int main(int argc, char* argv[])
{
void *shm = NULL;
struct stuShareMemory *stu = NULL;
int shmid = shmget((key_t)1234, sizeof(struct stuShareMemory), 0666|IPC_CREAT);
if(shmid == -1)
{
printf("shmget err.\n");
return 0;
}
shm = shmat(shmid, (void*)0, 0);
if(shm == (void*)-1)
{
printf("shmat err.\n");
return 0;
}
stu = (struct stuShareMemory*)shm;
stu->iSignal = 0;
//while(true) //如果需要多次 读取 可以启用 while
{
if(stu->iSignal != 1)
{
printf("write txt to shm.");
memcpy(stu->chBuffer, "hello world 666 - 888.\n", 30);
stu->iSignal = 1;
}
else
{
sleep(10);
}
}
shmdt(shm);
std::cout << "end progress." << endl;
return 0;
}
readShareMemory 文件:
//readShareMemory.cpp
#include "shmDatadef.h"
int main(int argc, char* argv[])
{
void *shm = NULL;
struct stuShareMemory *stu;
int shmid = shmget((key_t)1234, sizeof(struct stuShareMemory), 0666|IPC_CREAT);
if(shmid == -1)
{
printf("shmget err.\n");
return 0;
}
shm = shmat(shmid, (void*)0, 0);
if(shm == (void*)-1)
{
printf("shmat err.\n");
return 0;
}
stu = (struct stuShareMemory*)shm;
stu->iSignal = 1;
//while(true) //如果需要多次写入,可以启用while
{
if(stu->iSignal != 0)
{
printf("current txt : %s", stu->chBuffer);
stu->iSignal = 0;
}
else
{
sleep(10);
}
}
shmdt(shm);
shmctl(shmid, IPC_RMID, 0);
std::cout << "end progress." << endl;
return 0;
}
编译脚本:
# build.sh
rm -rf *.o readShareMemory writeShareMemory
g++ -Wall -o readShareMemory readShareMemory.cpp
g++ -Wall -o writeShareMemory writeShareMemory.cpp
Linux 查询指令
在 lLinux 系统中, 可以使用 ipcs -m
可以查看系统的共享内存,内容有键值(key),共享内存编号(shmid),创建者(owner),权限(perms),大小(bytes)。
更多推荐
已为社区贡献2条内容
所有评论(0)