【Linux】共享内存

共享内存

当多个进程需要在其间共享数据时,共享内存提供了一种高效的方式。它允许多个进程将同一块内存映射到它们的地址空间中,使得它们可以直接读写该内存,而不需要通过消息传递或其他形式的通信。

系统接口

在Linux中,使用共享内存需要以下步骤:

  1. 创建共享内存区域:使用shmget系统调用来创建一个共享内存区域,并指定大小和权限。
  2. 连接到共享内存区域:使用shmat系统调用将共享内存区域连接到进程的地址空间中,返回指向共享内存的指针。
  3. 使用共享内存:通过使用指针可以直接读写共享内存。
  4. 分离共享内存:使用shmdt系统调用将共享内存从进程的地址空间中分离。
  5. 删除共享内存区域:使用shmctl系统调用可以删除共享内存区域。
    共享内存是一种强大的进程间通信机制,但它也需要谨慎使用,因为多个进程可以直接修改共享内存中的数据,所以需要通过其他方式(如信号量)来确保数据的正确性和一致性。在编程中,可以使用C语言中的<sys/shm.h>头文件提供的函数来进行共享内存的操作。

当释放共享内存的时候,要先切断他们的映射关系,再释放共享区

创建共享内存区域 shmget
cpp 复制代码
//shmget所在的头文件和声明
#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

当创建成功后,返回共享内存的编号shmid,进程之间调用同一个共享内存的shmid是相等的

当创建失败后返回-1

key

  • 共享内存是操作系统在内存中申请的一块内存空间,操作系统中可能会有大量的共享内存,操作系统为了管理这些共享内存就要用相应的结构来进行描述,每个共享内存都有自己唯一的标识来代表。
  • 函数作用: 系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到
cpp 复制代码
	#include <sys/types.h>
    #include <sys/ipc.h>

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

pathname用于产生key_t值的文件名(文件必须存在)
proj_id的低序8位(不能为0)


size

  • size参数用于指明要创建的共享内存的大小,单位为字节。
  • 操作系统创建共享内存是以page页为单位的,大小为4KB。
    shmflg

shmflg参数用于指明shmget的使用模式。
IPC_CREAT and IPC_EXCL

单独使用IPC_CREAL:创建一个共享内存,如果共享内存不存在,就创建之,如果已经存在,获取已经存在的共性内存并返回
IPC_EXCL不能单独使用,一般都要配合IPC_CREAT
IPC_CREAT | IPC_EXCL:创建一个共享内存,如果共享内存不存在,就创建之,如果已经存在,则立马报错返回

-- 如果创建成功,对应的shm,一定是最新的

关联共享区域 shmat

当使用共享内存时,需要将其先与要映射的进程进行关联,才可以进行通信

cpp 复制代码
//shmat所在的头文件和声明
#include <sys/types.h>
#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);

shmid:shmget创建共享内存时的返回值
shmaddr:指明要关联到的地址处,传入空指针操作系统会自己进行关联。
shmflg:指明对要关联的共享内存的权限,传入0为读写权限。

如果关联成功则返回其对应的虚拟地址,失败返回-1

去除共享关联 shmdt

当要进行删除共享内存的时候,我们需要将其的关联全部去除后,才可以正常删除共享内存

cpp 复制代码
//shmdt所在的头文件和声明
#include <sys/types.h>
#include <sys/shm.h>

int shmdt(const void *shmaddr);

shmaddr:为共享关联时,返回的虚拟地址

成功返回0,失败返回-1

删除共享内存区域

当共享内存的进程退出的时候,我们的共享内存还是存在的,它是随的os的退出而退出,而不是进程退出它就退出的

删除共享区域的方式有两种一种为命令删除ipcrm -m

另一种为调用系统函数删除shmctl

ipcrm选项介绍

ipcs表示多个通信资源,选项包括队列(-q),共享内存(-m),信号量(-a)

我们需要查看我们的共享内存时,可以通过-m选项来查看

ipcrm -m 加 shmid可以删除一个共享内存,这里是不可以通过key删除的
key类比文件的inode
shmid类比文件的fd

shmctl选项介绍

cpp 复制代码
  #include <sys/ipc.h>
  #include <sys/shm.h>    

  int shmctl(int shmid, int cmd, struct shmid_ds *buf);

shmid:创建和读取共享进程时的返回值

cmd:对共享内存做操作(cmd选项有多种,其中包括,IPC_STAT 获取当前共享内存属性,IPC_SET 设置共享内存属性,IPC_RMID 标记这个段为释放)

*buf:获取共享内存字段属性,也是包括多种属性(删除时属性为nullptr)

如果函数发生错误返回-1

cpp 复制代码
	int n = shmctl(shmid, IPC_RMID, nullptr);
    assert(n != -1);
    (void)n;

共享内存特性

  • 无需多余拷贝:使用共享内存通信不需要任何接口,只要共享内存被映射到进程地址空间中,进程就能看到共享内存。
  • 速度快:共享内存被映射到进程的地址空间中,进程就能看到共享内存,不涉及缓冲区,无需多余拷贝动作,因此共享内存通信速度很快。
  • 无保护:使用共享内存通信不需要任何接口,因此共享内存不存在任何保护机制。
相关推荐
码农小白11 分钟前
linux驱动:(22)中断节点和中断函数
linux·运维·服务器
4647的码农历程12 分钟前
Linux网络编程 -- 网络基础
linux·运维·网络
醉颜凉37 分钟前
银河麒麟桌面操作系统V10 SP1:取消安装应用的安全授权认证
运维·安全·操作系统·国产化·麒麟·kylin os·安全授权认证
2401_8576100344 分钟前
SpringBoot实现:校园资料分享平台开发指南
服务器·spring boot·php
C++忠实粉丝1 小时前
Linux环境基础开发工具使用(2)
linux·运维·服务器
康熙38bdc2 小时前
Linux 环境变量
linux·运维·服务器
存储服务专家StorageExpert2 小时前
DELL SC compellent存储的四种访问方式
运维·服务器·存储维护·emc存储
hakesashou3 小时前
python如何比较字符串
linux·开发语言·python
Ljubim.te3 小时前
Linux基于CentOS学习【进程状态】【进程优先级】【调度与切换】【进程挂起】【进程饥饿】
linux·学习·centos
cooldream20093 小时前
Linux性能调优技巧
linux