共享内存

一、共享内存(Shared Memory)

1.1 基本概念

  • System V提供:UNIX操作系统的进程间通信方式

  • 特点:效率最高的IPC方式

1.2 操作流程

key → 申请对象 → 映射对象 → 读写对象 → 撤销映射 → 删除对象

1.3 与管道的区别

特性 共享内存 管道
读写权限 双方都可读写 半双工,固定读写端
阻塞 无读写阻塞 有读写阻塞
同步 需搭配其他IPC(信号/信号量) 自带同步
存储 内存区域(字符数组) 特殊文件
数据保留 数据保持,需主动清除 读取后剪切

1.4 相关函数接口

1.4.1 生成键值 ftok()
#include <sys/types.h>
#include <sys/ipc.h>

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

功能:通过路径和项目ID生成唯一键值
参数

  • pathname:任意存在且不常改变的文件路径

  • proj_id:项目ID(通常使用ASCII字符)
    返回值:成功返回键值,失败返回-1

1.4.2 申请共享内存 shmget()
#include <sys/ipc.h>
#include <sys/shm.h>

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

功能:申请共享内存
参数

  • key:唯一键值

  • size:申请的内存大小

  • shmflg:权限标志

    • IPC_CREAT:创建(如果不存在)

    • IPC_EXCL:检测是否存在

    • 权限:八进制数(如0666
      返回值:成功返回shmid,失败返回-1

1.4.3 映射共享内存 shmat()
void *shmat(int shmid, const void *shmaddr, int shmflg);

功能:将共享内存映射到进程地址空间
参数

  • shmid:共享内存ID

  • shmaddr:映射地址(通常为NULL,由系统分配)

  • shmflg:访问权限

    • 0:读写

    • SHM_RDONLY:只读
      返回值:成功返回映射地址,失败返回(void*)-1

1.4.4 读写共享内存
// 字符串操作
strcpy(shm_ptr, "Hello");
strcat(shm_ptr, " World");

// 内存操作
memcpy(shm_ptr, data, size);
memset(shm_ptr, 0, size);
memcmp(shm_ptr, data, size);

// 直接赋值
*(int*)shm_ptr = 100;
1.4.5 撤销映射 shmdt()
int shmdt(const void *shmaddr);

功能:断开共享内存映射
参数

  • shmaddr:映射地址
    返回值:成功返回0,失败返回-1

1.4.6 删除共享内存 shmctl()
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

功能:控制共享内存
参数

  • shmid:共享内存ID

  • cmd:控制命令

    • IPC_RMID:删除共享内存

  • buf:通常为NULL
    返回值:成功返回0,失败返回-1

1.5 示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>

#define SHM_SIZE 1024

int main() {
    // 1. 生成键值
    key_t key = ftok("/tmp", 'A');
    if (key == -1) {
        perror("ftok");
        exit(1);
    }
    
    // 2. 申请共享内存
    int shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);
    if (shmid == -1) {
        perror("shmget");
        exit(1);
    }
    
    // 3. 映射共享内存
    char *shm_ptr = (char*)shmat(shmid, NULL, 0);
    if (shm_ptr == (void*)-1) {
        perror("shmat");
        exit(1);
    }
    
    // 4. 读写共享内存
    sprintf(shm_ptr, "Hello from PID: %d", getpid());
    printf("Write to shm: %s\n", shm_ptr);
    
    sleep(2);  // 等待其他进程读取
    
    // 5. 撤销映射
    if (shmdt(shm_ptr) == -1) {
        perror("shmdt");
    }
    
    // 6. 删除共享内存(通常由最后一个进程执行)
    if (shmctl(shmid, IPC_RMID, NULL) == -1) {
        perror("shmctl");
    }
    
    return 0;
}

1.6 命令工具

# 查看所有IPC对象
ipcs -a

# 查看共享内存
ipcs -m

# 删除共享内存
ipcrm -m shmid

# 查看进程
ps aux | grep a.out

1.7 共享内存特性验证

  1. 数据存储方式:拷贝(不是剪切)

  2. 多次读写:会覆盖原有数据(无偏移时)

  3. 同步问题:需要配合其他IPC机制

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐