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 对于开发可靠的多进程应用程序非常重要。

相关推荐
北冥you鱼4 分钟前
Go 语言 CRUD 实战:从接口设计到真实业务场景
开发语言·后端·golang
企鹅侠客20 分钟前
Linux CPU 负载平均值(Load Average)详解:从原理到实践
linux·运维·服务器·服务器负载
易点云徐源26 分钟前
HP 暗影精灵 PRO 16 安装双系统后,开机直接进入 Windows,按 F9 才能进入 Ubuntu:GRUB 菜单不显示的处理方法
linux·运维·ubuntu
郭小李34 分钟前
springmvc 拦截器
java·开发语言·前端
web打印社区35 分钟前
Chrome-kiosk-printing能上生产吗
开发语言·前端·javascript·chrome·websocket
大风起兮云飞扬丶37 分钟前
Java——日期类
java·开发语言
Zwawa39 分钟前
从 printf 到曲线:把数据送上 VOFA+
c语言·单片机·嵌入式
Wang's Blog1 小时前
Java 项目实战:交友项目 - 联系人管理需求分析
java·开发语言·交友
第404号工位1 小时前
离职退电脑前别只点“清空回收站”!手把手教你彻底抹除凭证与数字痕迹
linux·python·架构
就像楞次定律1 小时前
【Linux 学习记之二】C++ 构建体系与底层链接机制的深度透视(1)
linux·后端