什么是共享内存
共享内存是进程间通信(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. 读写共享内存
多个进程只要用相同的键调用 shmget 和 shmat,就能访问同一块内存。比如进程 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] 手动清除。
实际开发中建议封装成模块,统一管理创建、销毁和错误处理,避免遗漏。