复习——共享内存
共享内存是UNIX系统中最高效的进程间通信方式,通过SystemV接口实现。其操作流程包括申请、映射、读写、撤销映射和删除对象。相比管道,共享内存具有双方读写权限、无阻塞等特点,但需要配合信号/信号量实现同步。关键函数包括ftok()生成键值、shmget()申请内存、shmat()映射内存等。示例代码展示了完整的共享内存使用流程,包括读写字符串和进程ID。系统提供ipcs/ipcrm等命令管理共
共享内存
一、共享内存(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 共享内存特性验证
-
数据存储方式:拷贝(不是剪切)
-
多次读写:会覆盖原有数据(无偏移时)
-
同步问题:需要配合其他IPC机制
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)