共享内存(shared memored),指的是指定某一特定的存储区域,使多个不同的进程都能在自己的进程地址空间访问到它。如果有一个进程改变了共享内存存储的数据,其他能访问到该共享内存的进程可以感知到数据的变化。

原理介绍

在Linux中,每个进程都有一个进程控制块(PCB) 和虚拟内存地址,通过页表,可以将虚拟内存映射为物理内存,共享内存就是是通过将不同进程的虚拟内存地址映射为相同的物理内存地址。调用共享内存时,首先操作系统会通过系统调用在物理内存中开辟一块内存,然后再将创建好的内存通过页表,映射到进程的虚拟地址空间中。当通信结束以后,进程就会取消掉物理内存和虚拟内存之间的映射关系,释放掉这块内存空间。

 

共享内存的应用场景

1.进程间通信

 

共享内存的实现方式 

Linux环境下,最常见的实现共享内存的方法的方式有两种,分别是:

  • 基于System V IPC的共享内存
  • 基于POSIX mmap实现共享内存

 

基于System V IPC 的共享内存

System V IPC(Inter-Process Communication)对象是一种用于在不同进程之间进行通信的机制。它包括三种类型的对象:消息队列(Message Queue)、信号量(Semaphore)和共享内存(Shared Memory)。这些机制都是通过Linux内核IPC设施实现的。通过ipcs命令可以查看ipc结构。

 

有两个东西可以用来标识一个IPC结构:IPC键值和IPC标识符。

  • IPC键值:IPC键值是一个整数。键值可以视为IPC对象的外部名,用来在进程间通信时使用。
  • IPC标识符:IPC标识符是一个非负整数,当创建一个新的IPC资源时,系统会分配一个唯一的标识符。标识符是IPC对象的内部名,外部不可见。使用根据IPC键值来查找IPC资源,返回对应的标识符。

使用时,一般先通过ftok函数创建IPC键值,再将该键值作为参数,调用具体的系统调用(如semget,msgget,shmget)获取具体的IPC标识符。

API介绍

@brief:ftok,将一个路径和一个整数标识转化成一个IPC键值

@params[in]:一个存在的路径名

@params[in]:整数标识符

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

 1 /**
 2  * @brief 创建IPC键
 3  * @author wangzequan
 4  * @date 2024/10/20
 5 */
 6 #include<iostream>
 7 #include<sys/ipc.h>
 8 #include<sys/shm.h>
 9 
10 int main(int argc, char*argv[])
11 {
12     key_t key;
13 
14     // 将一个路径和一个整数标识转化成一个IPC键值
15     key = ftok("./",0xa);
16     if(key<0)
17     {
18         perror("ftok error");
19         exit(1);
20     }
21 
22     return 0;
23 }

 

 

 

POSIX mmap实现共享内存

API介绍

 

实现示例