共享存储允许两个或多个进程共享一个给定的存储区,是进程间通信最快的一种方式。

不要同时对共享存储空间进行写操作,通常,信号量用于同步共享存储访问。

最简单的共享内存的使用流程

①ftok函数生成键值

②shmget函数创建共享内存空间

③shmat函数获取第一个可用共享内存空间的地址

④shmdt函数进行分离(对共享存储段操作结束时的步骤,并不是从系统中删除共享内存和结构)

⑤shmctl函数进行删除共享存储空间

1.ftok函数生成键值

每一个共享存储段都有一个对应的键值(key)相关联(消息队列、信号量也同样需要)。

所需头文件:#include<sys/ipc.h>

函数原型 :key_t ftok(const char *path ,int id);

path为一个已存在的路径名

id为0~255之间的一个数值,代表项目ID,自己取

返回值:成功返回键值(相当于32位的int)。出错返回-1

例如:key_t key = ftok( “/tmp”, 66);

2.shmget函数创建共享存储空间并返回一个共享存储标识符

所需头文件:#include<sys/shm.h>

函数原型: int shmget(key_t key, size_t size,int flag);

key为ftok生成的键值

size为共享内存的长度,以字节为单位

flag为所需要的操作和权限,可以用来创建一个共享存储空间并返回一个标识符或者获得一个共享标识符。

flag的值为IPC_CREAT:如果不存在key值的共享存储空间,且权限不为0,则创建共享存储空间,并返回一个共享存储标识符。如果存在,则直接返回共享存储标识符。

flag的值为 IPC_CREAT | IPC_EXCL:如果不存在key值的共享存储空间,且权限不为0,则创建共享存储空间,并返回一个共享存储标识符。如果存在,则产生错误。

返回值:成功返回共享存储ID;出错返回-1

例如:int id = shmget(key,4096,IPC_CREAT|IPC_EXCL|0666);创建一个大小为4096个字节的权限为0666(所有用户可读可写,具体查询linux权限相关内容)的共享存储空间,并返回一个整形共享存储标识符,如果key值已经存在有共享存储空间了,则出错返回-1。

int id = shmget(key,4096,IPC_CREAT|0666);创建一个大小为4096个字节的权限为0666(所有用户可读可写,具体查询linux权限相关内容)的共享存储空间,并返回一个共享存储标识符,如果key值已经存在有共享存储空间了,则直接返回一个共享存储标识符。

3.shmat函数获取第一个可用共享内存空间的地址

所需头文件:#include<sys/shm.h>

函数原型: void *shmat(int shmid, const void *addr, int flag);

shmid为shmget生成的共享存储标识符

addr指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置

flag为对数据的操作,如果指定为SHM_RDONLY则以只读方式连接此段,其他值为读写方式连接此段。

翻阅linux下shm.c文件得到#define SHM_RDONLY 010000 /* read-only access */

返回值:成功返回指向共享存储段的指针;错误返回-1(打印出指针的值为全F)

例如:char *addr = shmat(id, NULL, 0);就会返回第一个可用的共享内存地址的指针的值给addr

4.shmdt函数进行分离

当不需要对此共享内存进行操作时候,调用shmdt函数进行分离,不是删除此共享存储空间哟。

所需头文件:#include<sys/shm.h>

函数原型: int shmdt(const void *addr);

addr为shmat函数返回的地址指针

返回值:成功返回0;错误返回-1

例如:int ret = shmdt(addr);

5.shmctl函数对共享内存进行控制

简单的操作就是删除共享存储空间了,也可以获取和改变共享内存的状态

所需头文件:#include<sys/shm.h>

函数原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);

shmid就是shmget函数返回的共享存储标识符

cmd有三个,常用删除共享内存的为IPC_RMID;IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中;IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内。(内核为每个共享存储段维护着一个结构,结构名为shmid_ds,这里就不讲啦,里面存放着共享内存的大小,pid,存放时间等一些参数)

buf就是结构体shmid_ds

返回值:成功返回0;错误返回-1

例如:int ret = shmctl(id, IPC_RMID,NULL);删除id号的共享存储空间

在Linux下,比如你申请24字节大小的共享存储空间,系统还是会默认给你分配一页的大小,但你还是只能使用这一页上24字节的空间。使用getconf PAGE_SIZE 命令就能显示出一页的大小

使用ipcs -m可以查看当前系统所有的共享内存空间信息

如果你的程序创建了一个共享内存段,但没有销毁,可以使用命令ipcrm -m shmid命令删除共享内存段,不然程序再运行有可能出错。

实例

我创建了一个结构体,想让结构体存入共享内存。写了两个程序,service和client,代码基本相同,不同就是service程序的开始创建共享内存。这两个程序是一个死循环,让你选择是存数据还是读数据还是销毁共享内存。代码写的不是很精致,主要是为了练共享内存,见谅哈。

command.c文件,构造想存入的结构体,和共享内存的操作函数

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/shm.h>
#include "Command.h"
int sharememory(int ipc_size,int flag)
{int id;key_t key=ftok("/tmp",66);if(key < 0){printf("get key error\n");return -1;}id = shmget(key,ipc_size,flag);if(id < 0){printf("get id error\n");return -1;}return id;
}int create_ipc(int ipc_size)
{return sharememory(ipc_size,IPC_CREAT|IPC_EXCL|0666);
}
int get_ipc(int ipc_size)
{return sharememory(ipc_size,IPC_CREAT|0666);
}
int destroy_sharememory(int id)
{return shmctl(id,IPC_RMID,NULL);
}

ommand.h文件。好让service和client调用嘛,方便。

#define NAME_LEN 20
typedef struct {char name[NAME_LEN];int age;
}ckx;
int sharememory(int ipc_size,int flag);
int create_ipc(int ipc_size);
int get_ipc(int ipc_size);

service.c文件。创建共享内存空间啦,读写等

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<stdlib.h>
#include "Command.h"int main()
{int id=create_ipc(sizeof(ckx));int i=0;ckx *p;if(id < 0){printf("create sharememory error\n");return 0;}id = 0;while(1){printf("\n\n1.input data to sharememory\n2.get sharememory data\n\
3.destroy sharememory\ninput select:");scanf("%d",&i);if(i > 3 |i< 1){printf("input error\n");continue;}id = get_ipc(sizeof(ckx));if(id < 0){printf("get sharememory error\n");break;}p = (ckx *)shmat(id,NULL,0);if(p < 0){printf("get sharememory addr error\n");p = NULL;break;}if(i == 1){char name[NAME_LEN];int age=0;printf("input name:");fflush(stdin);getchar();gets(name);printf("input age:");scanf("%d",&age);strcpy(p->name,name);p->age = age;printf("write success\n");if(shmdt(p) == -1){printf("shmdt error\n");}id = 0;}if(i ==  2){printf("name:%s \t age:%d\n",p->name,p->age);if(shmdt(p) == -1){printf("shmdt error\n");break;}id = 0;}if(i == 3){if(shmdt(p) == -1){printf("shmdt error\n");break;}break;}}if(id !=0){if(destroy_sharememory(id)<0){printf("destroy error\n");}}
}

client.c基本上就和service.c代码差不多啦,只是想体现共享内存嘛,service读写和client读写,观察现象,体现共享内存

#include<stdio.h>
#include<sys/shm.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<stdlib.h>
#include "Command.h"int main()
{int i=0;ckx *p;int id = 0;while(1){printf("\n\n1.input data to sharememory\n2.get sharememory data\n\
3.destroy sharememory\ninput select:");scanf("%d",&i);if(i > 3 |i< 1){printf("input error\n");continue;}id = get_ipc(sizeof(ckx));if(id < 0){printf("get sharememory error\n");break;}p = (ckx *)shmat(id,NULL,0);if(p < 0){printf("get sharememory addr error\n");p = NULL;break;}if(i == 1){char name[NAME_LEN];int age=0;fflush(stdin);getchar();printf("input name:");gets(name);printf("input age:");scanf("%d",&age);strcpy(p->name,name);p->age = age;printf("write success\n");if(shmdt(p) == -1){printf("shmdt error\n");}id = 0;}if(i ==  2){printf("name:%s \t age:%d\n",p->name,p->age);if(shmdt(p) == -1){printf("shmdt error\n");break;}id = 0;}if(i == 3){if(shmdt(p) == -1){printf("shmdt error\n");break;}break;}}if(id !=0){if(destroy_sharememory(id)<0){printf("destroy error\n");}}
}

原文链接:https://blog.csdn.net/qq_27664167/article/details/81277096?utm_medium=distribute.pc_relevant_right.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant_right.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase

linux存储--共享内存机制shm(十四)相关推荐

  1. linux存储--共享内存机制shm(十三)

    实现进程间通信最简单也是最直接的方法就是共享内存--为参与通信的多个进程在内存中开辟一个共享区.由于进程可以直接对共享内存进行读写操作,因此这种通信方式效率特别高,但其弱点是,它没有互斥机制,需要信号 ...

  2. linux存储--共享内存机制mmap(十二)

    mmap基础概念 mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系.实现这样的映射关系后,进程就可以采用指 ...

  3. 【Linux】共享内存(shm)代码实现

    文章目录 共享内存介绍 最快的IPC形式 共享内存示意图 共享内存数据结构 共享内存函数 shmget函数 shmfig shmat函数 说明: shmdt函数 shmctl函数 共享内存的原理 小结 ...

  4. linux如何创建共享内存,linux实现共享内存同步的四种方法

    https://blog.csdn.net/sunxiaopengsun/article/details/79869115 本文主要对实现共享内存同步的四种方法进行了介绍. 共享内存是一种最为高效的进 ...

  5. 嵌入式Linux系统编程学习之二十三 System V 共享内存机制

    文章目录 前言 一.ftok 函数 二.shmget 函数 三.shmat 函数 四.shmdt 函数 五.shmctl 函数 补充 前言   共享内存也是进程间(进程间不需要有继承关系)通信的一种常 ...

  6. Linux内核在中国大发展的黄金十年-写于中国Linux存储、内存管理和文件系统峰会十周年之际...

    Linux阅码场: 国内首屈一指的专注Linux核心技术开发的公众号,扫描下方二维码关注 CLSF: CLSF是中国Linux存储.内存管理和文件系统峰会的简称, 至今已举办十年, 参会成员由组委会根 ...

  7. linux查看共享内存max,浅析Linux的共享内存与tmpfs文件系统

    浅析Linux的共享内存与tmpfs文件系统 前言 共享内存主要用于进程间通信,Linux有两种共享内存(Shared Memory)机制: (1)** System V shared memory( ...

  8. C语言之共享内存shm_open(二十五)

       在多个进程之间交换数据,在多个进程之间交换数据,最高效的方法莫过于共享内存.    linux共享内存是通过tmpfs这个文件系统来实现的,tmpfs文件系的目录为/dev/shm,/dev/s ...

  9. linux获取共享内存失败2,unix/linux共享内存应用与陷阱

    共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区.在/proc/sys/kernel/目录下,记录着共享内存的一些限制,如一 个共享内存区的最大字节数shmmax,系统范围内最大共享内存 ...

最新文章

  1. 2020-10-26runtime error: member access within null pointer of type ‘struct ListNode‘ (solution.cpp)错
  2. 【转载】Python常用模块之sys
  3. [转]Hadoop家族学习路线图
  4. Windows Server 2008 R2远程设置选项灰色解决方法
  5. 中国计算机学会CCF推荐国际学术会议和期刊目录(PDF版,2015年)
  6. 智力面试题汇总,有意思!
  7. JavaScript——仿键盘打字输入动画效果DEMO
  8. 2017 php7 使用率,让PHP7达到最高性能的几个Tips
  9. 信安教程第二版-第6章认证技术原理与应用
  10. mysql多张表join_mysql 连接查询(多表查询)+子查询-初学教程 3【重点】
  11. 权限判断 java_一个简单的关于权限判断登陆的javaBean文件
  12. 8月见!iQOO Pro 5G版即将亮相:骁龙855Plus加持
  13. 基于matlab的彩色图像分割,基于Matlab的彩色图像分割
  14. DPCM差分预测编码原理及实现
  15. STM32CUBEMX(5)--自定义红外NEC解码,定时器TIM捕获方式
  16. python操作腾讯文档_Python调用腾讯云接口
  17. 网络编程学习_TCP协议
  18. STM-1和SDH是什么关系?SONET与SDH是什么关系?
  19. 【学习记录】卷积神经网络常用概念
  20. char 与Unicode编码

热门文章

  1. 我在学python-我慌了,周围人都在学python...
  2. python掌握程度怎么判断-想要学习人工智能需要掌握Python到什么程度
  3. python视频教学视频哪个好-Python入门视频哪个好?
  4. python介绍和用途-Python --- Python的简介
  5. python用途与前景-Python 未来发展前景怎么样?
  6. python哪里下载import包-详解python中的模块及包导入
  7. python判断是否为类的实例,是否为子类
  8. 搜索github项目stars排名
  9. mysql数据库约束无符号_mysql 数据类型 约束条件
  10. matlab求kcf算法响应图_剖析KCF