共享内存机制

您所在的位置:网站首页 共享内存机制的原理是 共享内存机制

共享内存机制

2024-07-16 01:44:19| 来源: 网络整理| 查看: 265

共享内存是进程间通信的一种方法,常用到的有mmap和shm,下面做一个比较。

mmap机制:

在磁盘上建立一个文件,然后把文件内容映射到虚拟内存上,在每个进程的虚拟存储器里面,单独开辟一个空间来进行映射。在多进程情况下,不会对实际的物理存储器(主存)消耗太大。 即将一个文件或者其它对象映射到进程的虚拟地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一 一对映关系。 实现这样的映射关系后,进程就可以采用指针的方式操作这一段内存,而系统会自动回写到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享,也就是不再局限于具有亲缘关系的进程间通信。 简而言之,就是在进程虚拟空间上添加一个段,并将其与物理磁盘地址相连(映射),而在创建虚拟段的时候,并没有将任何文件数据拷贝至物理内存。

shm机制

多个进程的地址空间都映射到同一块物理内存,这样多个进程都能看到这块物理内存,实现进程间通信,而且不需要数据的拷贝,所以速度最快。当系统断电后,其中的文件会全部自行销毁,这点与mmap不同。

对比:

1、mmap是在磁盘上建立一个文件,每个进程地址空间中开辟出一块空间进行映射。而对于shm而言,shm每个进程最终会映射到同一块物理内存。shm保存在物理内存,这样读写的速度要比磁盘要快,但是存储量不是特别大。

2、mmap:磁盘->进程,shm:进程->内存(断电清除)。共享内存shm是在内存中创建空间,然后每个进程映射到此处;内存映射mmap是在磁盘中创建一个文件,然后每个进程映射到此处;

3 当机器重启时,mmap把文件保存在磁盘上,所以不会丢失,而共享内存shm存储在内存上就会丢失;

下面看一下mmap使用过程中要用到的一些接口:

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); //创建/访问 int munmap(void *addr, size_t length); //销毁

详细参数如下图:需要注意参数flags的含义,mmap文档的说明:

MAP_SHARED 共享这个映射。映射的更新对于映射同一区域的其他进程是可见的,并且(在文件备份映射的情况)被传送到底层文件。 MAP_PRIVATE 创建一个私有的写时复制的映射。映射的更新对映射同一文件的其他进程不可见,并且不被传送到底层文件。调用mmap()后对文件所做的更改是否在映射区域中可见,这是未指定的。 匿名映射 上面创建mmap映射区有一点不方便的地方,那就是每次建立映射区都需要依赖一个文件(.txt和fd或者其他)才能实现,通常为了建立映射区需要open一个临时文件,创建mmap好了之后再unlink、close比较麻烦。这时候可以直接使用匿名映射来代替,Linux系统提供了一个方法:借助mmap函数的标志位参数flags来制定:使用 MAP_ANONYMOUS(匿名的) 下面是一个简单的例子

#include #include #include #include #include #include #include extern "C"{ size_t strlen(const char *s); void *memcpy(void *dest, const void *src, size_t n); } /* * 这个是mmap的测试,适用于没有亲缘关系的进程或者两个不同的进程直接通信 * 并且是匿名共享内存,不需要创建临时文件 */ using std::cout; using std::endl; static int var = 666; //全局变量,进程间不共享 int main(){ int *p; pid_t pid; p = (int*)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if(p == MAP_FAILED){ perror("mmap"); exit(-1); } pid = fork(); //创建进程 if(pid == 0){ *p = 2000; //子进程修改 映射区的变量值 var = 100; //全局变量 cout //释放共享内存 perror("munmap"); exit(-1); } return 0; }

下面的简单案例中,我创建两个进程,并用指针p创建一个4字节的mmap,然后在子进程中给mmap中的内容赋值*p = 2000,然后在父进程中查看,可以看到由于设置了MAP_SHARE,所以父进程也可以读到相同的数据。顺便提一下:因为每个进程都有自己的独立地址空间,全局变量对于不同进程是不共享的,因此var是不同的。

下面是shm机制: 同样看一个测试:

#include #include #include #include #include #include #include using namespace std; struct stu { int num; char name[10]; char sex; }; int main() { int shmid; //共享内存标识符 //创建共享内存,键值为0x5005,共1024字节,全部用户可读写 if ( (shmid = shmget((key_t)0x5051, 3*sizeof(struct stu), 0666|IPC_CREAT)) == -1) { perror("shmget"); exit(-1); } //将共享内存连接到当前进程的地址空间(内存->进程),用ptext指向 stu* ptext = (stu*)shmat(shmid, 0, 0); //操作本程序的ptext指针,也就是操作共享内存,进行读写操作 cout cout s; ptext[i].num = n; strcpy(ptext[i].name, na); ptext[i].sex = s; } //把共享内存从当前进程中分离 shmdt(ptext); /* 删除共享内存 if (shmctl(shmid, IPC_RMID, 0) == -1){ perror("shmctl"); exit(-1); } */ return 0; }

可以看到,我的程序里每次写数据前,都对共享内存做了扫描,所以可以看到“上次写入的数据”,而本次写入就会覆盖原来的数据。 这里因为要提一下查看当前用户共享内存的属性的内容,就把最后一段共享内存删除的命令注释了。 linux系统下,可以用ipcs -m查看用户有"读"权限的共享内存的一些属性: 如下图第三段,键即为共享内存编号,和我在程序中调用shmget的第一个参数符合,是16进制表示方式。 shmid即为共享内存的标示,通过它我们可以删除共享内存,用到命令 ipcrm -m shmid



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭