Linux IPC:System V共享内存汇总整理

System V 共享内存是 Unix 和类 Unix 操作系统中的一种进程间通信(IPC)机制,它允许进程之间共享同一块内存区域。System V 共享内存是 System V IPC 标准的一部分,该标准还包括信号量和消息队列等其他 IPC 机制。

概述

System V 共享内存允许进程通过映射同一块内存区域来共享数据。与其他 IPC 机制相比,共享内存提供了更高的效率,因为它不需要复制数据就可以在进程之间传递信息。

特点

  • 持久性:共享内存段可以持久存储在内核中,即使创建它的进程终止后仍然存在。
  • 跨进程:共享内存可以在没有亲缘关系的进程之间进行通信。
  • 属性配置:可以配置共享内存段的属性,如最大大小等。

API

System V 共享内存主要由以下几个函数组成:

创建共享内存段

  • shmget() :
    • int shmget(key_t key, size_t size, int shmflg): 创建或打开共享内存段。
    • 参数key是标识共享内存段的键值,size指定共享内存段的大小,shmflg指定标志位,可以包含IPC_CREAT来创建新的共享内存段,也可以包含IPC_EXCL来防止创建已存在的共享内存段。

映射共享内存

  • shmat() :
    • void *shmat(int shmid, const void *shmaddr, int shmflg): 将共享内存段映射到进程地址空间。
    • 参数shmid是共享内存段标识符,shmaddr指定映射的起始地址,如果为NULL则由系统选择,shmflg指定标志位。

取消映射共享内存

  • shmdt() :
    • int shmdt(const void *shmaddr): 取消映射共享内存段。
    • 参数shmaddr是映射的起始地址。

删除共享内存段

  • shmctl() :
    • int shmctl(int shmid, int cmd, ... /* union shmid_ds *buf */): 控制共享内存段。
    • 参数shmid是共享内存段标识符,cmd指定命令,如IPC_RMID用于删除共享内存段,后面的参数根据命令的不同而变化。

示例代码

下面是一个简单的示例,展示了如何使用 System V 共享内存来在两个进程之间共享数据:

进程 A (processA.c)

复制代码
1#include <sys/types.h>
2#include <sys/ipc.h>
3#include <sys/shm.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
8#define SHM_KEY 12345
9#define SHM_SIZE 1024
10
11int main() {
12    int shmid;
13    char *shm_ptr;
14
15    // 创建共享内存段
16    shmid = shmget(SHM_KEY, SHM_SIZE, 0666 | IPC_CREAT);
17    if (shmid == -1) {
18        perror("shmget");
19        exit(EXIT_FAILURE);
20    }
21
22    // 映射共享内存段到进程地址空间
23    shm_ptr = shmat(shmid, NULL, 0);
24    if (shm_ptr == (void *)-1) {
25        perror("shmat");
26        exit(EXIT_FAILURE);
27    }
28
29    // 写入数据
30    strncpy(shm_ptr, "Hello, World!", SHM_SIZE);
31
32    // 取消映射
33    if (shmdt(shm_ptr) == -1) {
34        perror("shmdt");
35        exit(EXIT_FAILURE);
36    }
37
38    return 0;
39}

进程 B (processB.c)

复制代码
1#include <sys/types.h>
2#include <sys/ipc.h>
3#include <sys/shm.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
8#define SHM_KEY 12345
9#define SHM_SIZE 1024
10
11int main() {
12    int shmid;
13    char *shm_ptr;
14
15    // 打开共享内存段
16    shmid = shmget(SHM_KEY, SHM_SIZE, 0666);
17    if (shmid == -1) {
18        perror("shmget");
19        exit(EXIT_FAILURE);
20    }
21
22    // 映射共享内存段到进程地址空间
23    shm_ptr = shmat(shmid, NULL, 0);
24    if (shm_ptr == (void *)-1) {
25        perror("shmat");
26        exit(EXIT_FAILURE);
27    }
28
29    // 读取数据
30    printf("Data in shared memory: %s\n", shm_ptr);
31
32    // 取消映射
33    if (shmdt(shm_ptr) == -1) {
34        perror("shmdt");
35        exit(EXIT_FAILURE);
36    }
37
38    // 删除共享内存段
39    if (shmctl(shmid, IPC_RMID, NULL) == -1) {
40        perror("shmctl");
41        exit(EXIT_FAILURE);
42    }
43
44    return 0;
45}

编译和运行

为了编译上述代码,你可以使用以下命令:

复制代码
1gcc -o processA processA.c
2gcc -o processB processB.c

然后运行这两个进程:

复制代码
1./processA &
2./processB

注意事项

  • 在使用 System V 共享内存之前,确保检查所有 API 调用的返回值,以确保操作成功。
  • 当使用完共享内存后,记得取消映射并删除共享内存段以释放资源。
  • 如果共享内存段不再需要,应使用 shmctl()IPC_RMID 命令删除它,以避免占用不必要的系统资源。
  • 在实际应用中,可能需要处理更复杂的错误情况,比如处理映射失败的情况。

System V 共享内存提供了一种简单而强大的机制来进行进程间的共享数据,非常适合那些需要快速访问共享数据的应用场景。理解和熟练掌握这些 API 对于开发可靠的多进程应用程序非常重要。

相关推荐
海上Bruce1 小时前
C primer plus (第六版)第十章 编程练习第7,8,9,10,11题
c语言
仟濹1 小时前
【C/C++】整数超过多少位时用「高精度」
c语言·c++·算法
夏影孤灯1 小时前
C 语言问题
c语言·开发语言
筵陌5 小时前
Linux线程概念与控制(下)
linux
新手小新5 小时前
C++游戏开发(2)
开发语言·前端·c++
你的电影很有趣5 小时前
lesson30:Python迭代三剑客:可迭代对象、迭代器与生成器深度解析
开发语言·python
-SGlow-6 小时前
MySQL相关概念和易错知识点(3)(表内容的CURD、内置函数)
linux·运维·服务器·数据库·mysql
永远向阳而生7 小时前
【Linux】磁盘存储+文件系统简介
linux
程序员编程指南7 小时前
Qt 嵌入式界面优化技术
c语言·开发语言·c++·qt
君不见~7 小时前
Windows 10 WSL&Ubuntu 22.04 安装并迁移到 F 盘
linux·ubuntu·wsl迁移盘符·wsl迁移