栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

【linux之进程通信】——共享内存

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【linux之进程通信】——共享内存

目录

.共享内存的机制

. 创建共享内存

. shmget函数

.ftok函数

. shmctl函数 

 . shmat函数

. shmdt函数

. 代码实例

.区分key值和shmid

. 管道的方式进行通信

往期linux文章


.共享内存的机制

让进程拿出一块虚拟地址空间来,映射到相同的内存中,使不同的进程都能看到同一块空间,

 这样就能实现不同的进程进行通信。

 

. 创建共享内存

. shmget函数
int shmget(key_t key, size_t size, int shmflg); 功能:创建一个共享内存 key:在内核中标识共享内存的标识符,需要用ftok函数来创建。 size:创建共享内存的大小 shmflg:参数选项,如下:
  • IPC_CREAT:如果该key值有对应的共享内存,则返回该共享内存的标识符,如果不存在,则创建共享内存,并返回该共享内存的标识符,单纯一个IPC_CREAT的参数是不能判断shmget是否创建全新的共享内存。
  • IPC_CREAT|IPC_EXCL:如果该key值有对应的共享内存不存在,则会出错返回,不然则创建新的共享内存,可以确保创建的共享内存是全新的。
返回值:成功返回一个非负整数,即共享内存的标识符shmid,是在进程层面上进行标识的。失败返回-1.

.ftok函数

       #include
       #include

       key_t ftok(const char *pathname, int proj_id);

       功能:将pathname和proj_id根据某种算法生成一个key值,用来区分内核中的共享内存和消息队列,信号量。

     pathname:指定一个已存在的文件,且这个文件是可以访问的

      proj_id:  可以根据自己的约定,随意设置。这个数字,有的称之为project ID; 在UNIX系统上,它的取值是1到255;

     返回值:返回一个key值

. shmctl函数 

功能:用于控制共享内存 原型 int shmctl(int shmid, int cmd, struct shmid_ds *buf); 参数 shmid :共享内存的标识符, 由 shmget 返回的共享内存标识符 cmd : 将要采取的动作
  • IPC_RMID:删除共享内存
buf : 指向一个保存着共享内存的模式状态和访问权限的数据结构 返回值 :成功返回 0 ;失败返回 -1

 . shmat函数
功能:将共享内存段映射到进程地址空间 原型 void *shmat(int shmid, const void *shmaddr, int shmflg);、 参数: shmid :共享内存标识符,即shmget返回的值。 shamaddr :指定连接地址。如果传NULL,则系统会自动在该进程的虚拟内存选一个合适的地址。 shmflg :
  • 0:读写方式
  • SHM_RDONLY:为只读模式。

返回值:成功返回的是共享内存映射该进程虚拟内存上的起始地址,失败返回-1.

. shmdt函数

功能:取消共享内存与进程虚拟内存的映射

原型:int shmdt(const void *shmaddr);

参数:

shmaddr:映射在共享内存的虚拟地址,即shmat的返回值。

返回值:成功返回0,失败返回-1.

两个进程通过共享内存进行通信的过程:
先利用ftok生成一个key值,然后利用这个key值,创建出一个共享内存,使进程A和进程B都能看到这块共享内存,然后将这块共享内存与进程A和进程B的虚拟内存进行映射,通信完毕的时候,取消共享内存和进程A和进程B的虚拟地址之间的映射,然后再将共享内存给删掉即可。
开始通信: 第一步:创建共享内存

 第二步:将共享内存映射到进程的虚拟地址上 

结束通信时:

第一步:取消映射

 

 第二步:删除共享内存

. 代码实例

makefile文件

 

comm.h文件

 server.c

1.如果创建的共享内存没有指定权限的话,那么创建出来的共享内存是没有任何权限,是无法与我们进程的虚拟地址建立映射关系。 

2.如果共享内存已存在,则IPC_CREAT|IPC_EXCL会直报错退出。

3.同一个pathname,proj_id生成的key值是一样的,接下来client.c文件生成的key是一样的,所以它们找到的是同一个共享内存。

 client.c

 

 

运行结果:

 

当我们创建共享内存后,我们应该怎样查看内核中的共享内存;

ipcs -m  查看系统中的共享内存

 

ipcrm -m shmid 删除某个共享内存

 

.区分key值和shmid

key值和shmid它们都是共享内存的标识符,那么我们怎么理解这两个数字呢?

key值是在内核中标识共享内存的唯一性的方式,也就是说操作系统要找到某个共享内存,就通过key值进行查找。

shmid值是进程内部标识共享内存的唯一性的方式,进程想要找共享内存,就通过shmid值去查找。

总结:shmid值是对key值进行了封装,它是在进程内部进行区分的,如果进程想要去内核中找共享内存,就需要通过shmid值找到key值,然后通过key值找到我们的共享内存。

. 共享内存的方式进行通信

文件1通过进程虚拟内存和共享内存的映射关系,可以直接往共享内存上写入数据,文件2可以将共享内存的数据直接写到文件2上。

 

. 管道的方式进行通信

如图所示:

 文件1是不能将数据直接写道我们的管道上,需要先将数据直接写到进程A上,然后再将数据写入到管道,进程也不能直接将数据写入到文件2,提取需要在管道中提取数据,然后才可以写入到文件2.

因此,进程往共享内存中写入数据,另一个进程可以立马可以看到,所以共享内存的通信效率是非常快的。

往期linux文章

【linux之进程间通信】——管道

【linux】——动静态库

【linux】——基本的文件操作 

【linux】——文件系统

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/456883.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号