共享内存原理,ftok(key的形成),shmget,shmid和key的介绍和关系,shmat,shmdt(共享内存的生命周期),shctl,共享内存结构体,ipcrm命令

共享内存是一种有效的进程间通信方式,通过ftok获取key,shmget创建或访问内存,shmat连接进程和内存,shmdt断开连接。文章详细阐述了共享内存的原理、管理、使用方法和生命周期,包括key和shmid的作用,以及相关函数的使用示例。
摘要由CSDN通过智能技术生成

目录

共享内存

引入

原理

位置

如何管理

思考原理 

使用

ftok() -- 获取key

函数原型

返回值 -- key

key的形成

不同进程获得相同key

shmget -- 使用key获得共享内存

函数原型

key

size

shmflg

IPC_CREAT

IPC_EXCL

空间的权限

shmflg为0时

示例

返回值 -- shmid

key和shmid的关系

shmid -- 用户层标识符

key -- 内核层标识符

shmat -- 连接进程和共享内存

函数原型

shmid

shmaddr

shmflg

返回值

shmdt -- 使进程和共享内存脱离连接

函数原型

shmaddr

作用

注意点 -- 共享内存的生命周期

返回值

shmctl -- 控制共享内存

shmid

cmd

buf

struct shmid_ds类型的结构体

ipcrm -m + shmid


共享内存

引入

原理

  • 还记得我们的动态库吗,它可以实现内存中只加载一份库,却可以映射到多个进程中
  • 我们可以将 [动态库的原理] 和 [通信本质--让不同进程看到同一份资源]结合起来想
  • 也就是 -- os自己申请一部分空间,同样映射到多个进程中,也就能实现多个进程访问同一块空间

位置

  • 既然是一块空间,当进程访问的时候,就要放在它的地址空间
  • 这部分叫做内存映射区域

如何管理

  • 如果有多个进程都在使用这块共享内存,或者有多个共享内存,是不是需要os来管理他们?
  • 也就是--先描述,再组织
  • 首先,是不是需要统计这块内存被几个进程使用着,以及其他的属性也需要被记录
  • 这就需要我们额外的空间来记录这些信息,而这些信息也就描述了这块空间的属性等等
  • 所以,共享内存 = 共享内存块 + 对应的内核数据结构

思考原理 

在介绍使用方法之前,我们可以自己先来思考一下究竟该如何实现

  • 首先,我们要开辟一块空间
  • 最重要的是 -- 要保证不同进程可以通过某种方式拿到同样的空间
  • 之后就可以对这块空间进行读写

  • 但是!!!如果多个进程同时进行io,究竟谁先谁后呢?
  • 在不知道对方动作的情况下,很可能导致数据读写并不符合我们的预期

  • 最后就是资源泄漏问题,如果当前共享内存已经没有进程访问了,就需要释放空间了

接下来就是正式开始介绍了 

使用

ftok() -- 获取key

函数原型

返回值 -- key
  • 每个进程通过key来识别和访问共享的系统资源
  • 相当于可以通过这个特定的key值找到对应的共享空间(我们要保证通信的双方访问同一块空间)
key的形成
  • 路径名整数标识符两个参数,通过某个算法形成
  • 用于唯一标识一个特定的系统资源
不同进程获得相同key

通过使用相同的路径名和标识符调用ftok()函数,可以实现对同一共享资源的访问

shmget -- 使用key获得共享内存

函数原型

 使用示例:

int shmid = shmget(key, SUM_SIZE, IPC_CREAT|IPC_EXCL|0666);
key

用于标识生成的这块共享内存

size
  • 共享内存大小
  • 一般是页大小的整数倍 (在x86架构的计算机中,通常使用的页大小是4KB(4096字节))
  • 如果设置的大小不是整数倍,会浪费空间资源 (因为只能使用页的倍数来开辟空间)
shmflg

控制共享内存段的创建和访问方式

IPC_CREAT

创建新的共享内存

IPC_EXCL
  • 确保不覆盖已存在的共享内存(保证返回的是新的共享内存)
  • 不可以单独使用
空间的权限

使用八进制数表示

shmflg为0时

示例

这里我们的key没有对应的共享内存块,所以shmid返回了-1:

返回值 -- shmid

  • 获取失败,返回-1
  • 成功,返回这块共享内存的shmid

key和shmid的关系

在创建或访问共享内存段时,key用于指定共享内存段,而shmid用于后续的操作和访问

也就是 -- key标识共享内存,shmid在shmget()中与key关联,给上层使用

shmid -- 用户层标识符
  • 可以被用于其他System V IPC函数(如shmat、shmdt等)来操作和访问共享内存段
key -- 内核层标识符
  • 是一个32位的整数值
  • 用于在进程间共享内存、信号量和消息队列等系统资源之间进行标识和访问 
  • 由ftok()根据给定的路径名和标识符生成
  • shmget函数的调用中用于指定要创建或访问的共享内存段,也就是将key和shmid关联起来

shmat -- 连接进程和共享内存

函数原型

shmid

将要连接的共享内存段的用户级标识符

shmaddr
  • 指定共享内存段的附加地址
  • 通常将其设置为NULL,表示由os自动选择合适的地址
shmflg
  • 用于指定连接方式的标识位
  • 通常为0,表示以默认的方式连接共享内存
  • 在默认情况下,连接是读写的,而且系统会选择合适的地址来附加共享内存段
返回值

  • 返回共享内存段的起始地址
  • 可以将共享内存块想象成一个特定大小的字符串,起始地址也就是字符串的起始地址
  • 如果失败,返回-1

shmdt -- 使进程和共享内存脱离连接

函数原型

shmaddr

指向共享内存段的起始地址(也就是shmat()的返回值)

作用
  • 将共享内存段从调用进程的地址空间中分离
  • 分离后,进程将无法继续访问和操作该共享内存段中的数据
  • 在使用共享内存段后,应及时调用shmdt函数将其分离,以释放系统资源并确保正确的内存管理
注意点 -- 共享内存的生命周期
  • 调用shmdt函数只是分离共享内存段并不会删除或销毁该共享内存段
  • 因此可以知道共享内存的生命周期不是随进程的,而是随os
返回值
  • 成功分离共享内存段时,shmdt函数返回0
  • 失败时,返回-1

shmctl -- 控制共享内存

函数原型

用于执行各种共享内存段的操作

shmid

共享内存段的用户级标识符

cmd

指定要执行的操作的命令的标识符

buf
  • 指向struct shmid_ds类型的结构体的指针(这个结构体在<sys/shm.h>中定义)
  • 用于传递或接收与共享内存段相关的信息
struct shmid_ds类型的结构体
  • 这个也就是前面说的 -- 用于描述共享内存的数据结构
  • 当我们想定义它的属性,就可以通过这个来定义,然后传递给shctl函数

(当我们执行删除操作时,是不需要这个结构体的,直接传入nullptr即可)

ipcrm -m + shmid

在命令行中使用

从系统中删除对应的共享内存标识符

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值