【Linux】共享内存

      • 共享内存
      • 系统接口
        • 创建共享内存区域 shmget
        • 关联共享区域 shmat
        • 去除共享关联 shmdt
        • 删除共享内存区域
      • 共享内存特性

共享内存

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

系统接口

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

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

【Linux】共享内存_第1张图片

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

创建共享内存区域 shmget
//shmget所在的头文件和声明
#include 
#include 

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

当创建成功后,返回共享内存的编号shmid,进程之间调用同一个共享内存的shmid是相等的
当创建失败后返回-1
【Linux】共享内存_第2张图片

key
【Linux】共享内存_第3张图片

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

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

pathname用于产生key_t值的文件名(文件必须存在)
proj_id的低序8位(不能为0)
【Linux】共享内存_第4张图片
【Linux】共享内存_第5张图片

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);

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

去除共享关联 shmdt

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

//shmdt所在的头文件和声明
#include 
#include 

int shmdt(const void *shmaddr);

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

删除共享内存区域

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

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

ipcrm选项介绍

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

ipcrm -m 加 shmid可以删除一个共享内存,这里是不可以通过key删除的
key类比文件的inode
shmid类比文件的fd
【Linux】共享内存_第7张图片

shmctl选项介绍

  #include 
  #include     

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

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

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

共享内存特性

  • 无需多余拷贝:使用共享内存通信不需要任何接口,只要共享内存被映射到进程地址空间中,进程就能看到共享内存。
  • 速度快:共享内存被映射到进程的地址空间中,进程就能看到共享内存,不涉及缓冲区,无需多余拷贝动作,因此共享内存通信速度很快。
  • 无保护:使用共享内存通信不需要任何接口,因此共享内存不存在任何保护机制。

你可能感兴趣的:(Linux,linux,运维,服务器)