Unix共享内存单标识符场景下多指针使用方案咨询
解决单共享内存ID下使用多个指针的问题
你的当前代码存在一个关键问题:两次调用Shmat会返回同一个共享内存段的起始地址,所以mem和mem2其实指向同一块内存的开头,完全达不到你想要的"多个指针访问不同区域"的效果。下面给你两种可行的解决方案,核心思路都是在同一个共享内存段内划分不同的区域,通过偏移或结构化的方式获取不同的指针。
方案一:通过内存偏移划分区域
如果你只是需要简单的不同类型/大小的内存块,可以直接计算总内存大小,分配后通过起始地址的偏移得到不同指针:
#include <sys/shm.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { // 定义需要的内存:1个int变量 + 50个char的缓冲区 const size_t int_size = sizeof(int); const size_t char_buf_size = 50; const size_t total_shm_size = int_size + char_buf_size; // 创建共享内存段 int idSh = shmget(IPC_PRIVATE, total_shm_size, IPC_CREAT | 0700); if (idSh == -1) { perror("shmget failed"); exit(EXIT_FAILURE); } // 挂载共享内存到进程地址空间 void* base_addr = shmat(idSh, NULL, 0); if (base_addr == (void*)-1) { perror("shmat failed"); exit(EXIT_FAILURE); } // 通过偏移获取不同指针 int* mem = (int*)base_addr; // 指向共享内存起始的int区域 char* mem2 = (char*)(base_addr + int_size); // 指向int区域之后的char缓冲区 // 测试使用 *mem = 1234; strcpy(mem2, "Hello Shared Memory!"); printf("mem value: %d\n", *mem); printf("mem2 value: %s\n", mem2); // 记得卸载共享内存(实际开发中根据场景处理) shmdt(base_addr); shmctl(idSh, IPC_RMID, NULL); return 0; }
方案二:使用结构体结构化共享内存
如果你的数据结构更复杂,推荐在共享内存中定义一个结构体,通过结构体成员来获取不同的指针,代码可读性更强:
#include <sys/shm.h> #include <stdio.h> #include <stdlib.h> #include <string.h> // 定义共享内存中的数据结构 typedef struct { int counter; char message[100]; float temperature; } SharedData; int main() { const size_t total_shm_size = sizeof(SharedData); // 创建共享内存 int idSh = shmget(IPC_PRIVATE, total_shm_size, IPC_CREAT | 0700); if (idSh == -1) { perror("shmget failed"); exit(EXIT_FAILURE); } // 挂载并转为结构体指针 SharedData* shared_data = (SharedData*)shmat(idSh, NULL, 0); if (shared_data == (void*)-1) { perror("shmat failed"); exit(EXIT_FAILURE); } // 获取指向不同成员的指针 int* mem = &shared_data->counter; char* mem2 = shared_data->message; float* mem3 = &shared_data->temperature; // 测试使用 *mem = 99; strcpy(mem2, "Structured shared memory works!"); *mem3 = 25.6f; printf("Counter: %d\n", *mem); printf("Message: %s\n", mem2); printf("Temperature: %.1f\n", *mem3); // 清理资源 shmdt(shared_data); shmctl(idSh, IPC_RMID, NULL); return 0; }
关键注意事项
- 永远不要忽略
shmget和shmat的返回值检查,这些系统调用很容易因为权限、内存不足等原因失败。 - 跨进程使用时,不要在共享内存中存放指针(比如
char*类型的成员),因为不同进程的地址空间映射不同,指针在其他进程中无效。直接存放实际数据(比如固定大小的数组)才是安全的。 - 使用完共享内存后,记得通过
shmdt卸载,以及shmctl(IPC_RMID)删除(避免系统资源泄漏)。
内容的提问来源于stack exchange,提问作者Homer Simpsons
相关产品推荐
相关产品推荐

