共享内存分配使用步骤详解

什么是共享内存

共享内存是进程间通信(IPC)中最高效的方式之一。它允许多个进程访问同一块内存区域,避免了频繁的数据拷贝,特别适合需要高速数据交换的场景,比如音视频处理、高频交易系统或大型游戏服务器。

想象一下两个同事共用一块白板记录任务进度,谁都可以随时查看和修改,效率自然比各自记在本子上再互相通报要高得多。

共享内存分配使用步骤

1. 创建或打开共享内存段

使用 shmget 函数来创建或获取一个共享内存标识符。你需要指定一个键值(key)、所需内存大小以及权限标志。

#include <sys/shm.h>

int shmid = shmget(1234, 4096, IPC_CREAT | 0666);
if (shmid == -1) {
    perror("shmget failed");
    exit(1);
}

这里键值 1234 是用户自定义的,4096 表示申请 4KB 内存,IPC_CREAT 表示如果不存在就创建。

2. 将共享内存映射到进程地址空间

创建后还不能直接使用,必须通过 shmat 将其附加到当前进程的地址空间。

char *data = (char *)shmat(shmid, NULL, 0);
if (data == (char *)-1) {
    perror("shmat failed");
    exit(1);
}

此时 data 就是指向共享内存的指针,可以像操作普通内存一样读写。

3. 读写共享内存

多个进程只要用相同的键调用 shmgetshmat,就能访问同一块内存。比如进程 A 写入:

strcpy(data, "Hello from Process A");

进程 B 就能读出:

printf("Received: %s\n", data);

注意:没有内置同步机制,读写冲突需自行控制,通常配合信号量使用。

4. 解除映射

进程用完后应解除映射,避免资源泄漏。

if (shmdt(data) == -1) {
    perror("shmdt failed");
}

这一步只是断开连接,并不删除共享内存段。

5. 删除共享内存段

当所有进程都不再使用时,由其中一个进程调用 shmctl 删除。

if (shmctl(shmid, IPC_RMID, NULL) == -1) {
    perror("shmctl IPC_RMID failed");
}

加上 IPC_RMID 标志后,系统会标记该内存段为可回收,待无进程挂接后自动释放。

常见问题提醒

共享内存不会随程序退出自动清理。如果程序异常终止,可能留下“僵尸”内存段,可通过命令 ipcs -m 查看,用 ipcrm -m [shmid] 手动清除。

实际开发中建议封装成模块,统一管理创建、销毁和错误处理,避免遗漏。