• 【Linux】共享内存


    共享内存

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

    系统接口

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

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

    在这里插入图片描述

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

    创建共享内存区域 shmget
    //shmget所在的头文件和声明
    #include 
    #include 
    
    int shmget(key_t key, size_t size, int shmflg);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    当创建成功后,返回共享内存的编号shmid,进程之间调用同一个共享内存的shmid是相等的
    当创建失败后返回-1
    在这里插入图片描述

    key
    在这里插入图片描述

    • 共享内存是操作系统在内存中申请的一块内存空间,操作系统中可能会有大量的共享内存,操作系统为了管理这些共享内存就要用相应的结构来进行描述,每个共享内存都有自己唯一的标识来代表。
    • 函数作用: 系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到
    	#include 
        #include 
    
        key_t ftok(const char *pathname, int proj_id);
    
    • 1
    • 2
    • 3
    • 4

    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

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

    //shmat所在的头文件和声明
    #include 
    #include 
    
    void *shmat(int shmid, const void *shmaddr, int shmflg);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    shmid:shmget创建共享内存时的返回值
    shmaddr:指明要关联到的地址处,传入空指针操作系统会自己进行关联。
    shmflg:指明对要关联的共享内存的权限,传入0为读写权限。
    如果关联成功则返回其对应的虚拟地址,失败返回-1

    去除共享关联 shmdt

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

    //shmdt所在的头文件和声明
    #include 
    #include 
    
    int shmdt(const void *shmaddr);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    shmaddr:为共享关联时,返回的虚拟地址
    成功返回0,失败返回-1

    删除共享内存区域

    当共享内存的进程退出的时候,我们的共享内存还是存在的,它是随的os的退出而退出,而不是进程退出它就退出的
    删除共享区域的方式有两种一种为命令删除ipcrm -m

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

    ipcrm选项介绍

    ipcs表示多个通信资源,选项包括队列(-q),共享内存(-m),信号量(-a)
    在这里插入图片描述
    我们需要查看我们的共享内存时,可以通过-m选项来查看
    在这里插入图片描述

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

    shmctl选项介绍

      #include 
      #include     
    
      int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    
    • 1
    • 2
    • 3
    • 4

    shmid:创建和读取共享进程时的返回值
    cmd:对共享内存做操作(cmd选项有多种,其中包括,IPC_STAT 获取当前共享内存属性,IPC_SET 设置共享内存属性,IPC_RMID 标记这个段为释放)
    *buf:获取共享内存字段属性,也是包括多种属性(删除时属性为nullptr)
    如果函数发生错误返回-1

    	int n = shmctl(shmid, IPC_RMID, nullptr);
        assert(n != -1);
        (void)n;
    
    • 1
    • 2
    • 3

    共享内存特性

    • 无需多余拷贝:使用共享内存通信不需要任何接口,只要共享内存被映射到进程地址空间中,进程就能看到共享内存。
    • 速度快:共享内存被映射到进程的地址空间中,进程就能看到共享内存,不涉及缓冲区,无需多余拷贝动作,因此共享内存通信速度很快。
    • 无保护:使用共享内存通信不需要任何接口,因此共享内存不存在任何保护机制。
  • 相关阅读:
    java计算机毕业设计基于springboot校园新闻网站
    为什么自动驾驶需要5G?
    P8352-[SDOI/SXOI2022]小N的独立集【dp套dp】
    【2022PMP最全总结-从报名、考试、成绩结果(3A)一条龙教程】
    9.1充血模型和贫血模型
    什么是异常处理,Python常见异常类型
    软件开发模型、瀑布模型、V模型、原型模型、增量模型、螺旋模型、喷泉模型
    基于springboot、vue汽车租赁系统
    vue3子组件调用父组件的方法
    C与C++字符串方法示例
  • 原文地址:https://blog.csdn.net/wh9109/article/details/132837994