System V共享内存shmat:如何存放单个int与结构体数组?
System V共享内存使用问题解答
问题1:单个int与结构体数组能否存入同一段共享内存?若需分开,是否要额外调用shmget和shmat?
- 完全可以存入同一段共享内存,不需要分开。只需要计算好总内存大小(
sizeof(int) + 数组元素个数 * sizeof(struct My_structure)),用这个总大小调用shmget即可,无需额外调用shmget和shmat。
问题2:如何正确编写带错误处理的shmat代码?当前代码出现“指针与整数比较”的警告
- 警告原因:
shmat失败时返回的是(void*)-1(指针类型),直接将其强制转换为struct My_structure*后和整数-1比较,C语言不允许指针与整数直接比较,因此触发警告。 - 正确写法:先将
shmat的返回值存入void*类型变量,与(void*)-1比较判断是否失败,再转换为目标指针类型:
void *shm_raw; struct My_structure *shm_pointer; if ((shm_raw = shmat(shm_id, NULL, 0)) == (void *)-1) { perror("shmat failed"); exit(EXIT_FAILURE); } shm_pointer = (struct My_structure *)shm_raw;
问题3:如何让共享内存中的数据支持类似array[number]的数组式访问?
- 由于共享内存中先存储单个int,再存储结构体数组,需要分别定位两者的内存地址:
- 单个int的地址就是共享内存的起始地址,直接转换为
int*即可访问; - 结构体数组的起始地址是共享内存起始地址加上单个int的大小,转换为
struct My_structure*后,就可以像普通数组一样用下标访问。
- 单个int的地址就是共享内存的起始地址,直接转换为
完整示例代码
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string.h> struct My_structure { char my_text[200]; char my_name[20]; int my_number; }; int main(int argc, char *argv[]) { key_t key; int shm_id; void *shm_start; int *unrelated_singular_int; struct My_structure *struct_array; const int array_len = 5; // 假设结构体数组长度为5 size_t total_shm_size = sizeof(int) + array_len * sizeof(struct My_structure); if (argc < 2) { fprintf(stderr, "Usage: %s <file_path>\n", argv[0]); exit(EXIT_FAILURE); } // 生成共享内存键值 if ((key = ftok(argv[1], 2137)) == -1) { perror("ftok failed"); exit(EXIT_FAILURE); } // 创建/获取共享内存段 if ((shm_id = shmget(key, total_shm_size, 0644 | IPC_CREAT)) == -1) { perror("shmget failed"); exit(EXIT_FAILURE); } // 挂载共享内存 if ((shm_start = shmat(shm_id, NULL, 0)) == (void *)-1) { perror("shmat failed"); exit(EXIT_FAILURE); } // 访问单个int变量 unrelated_singular_int = (int *)shm_start; *unrelated_singular_int = 100; printf("Singular int value: %d\n", *unrelated_singular_int); // 访问结构体数组 struct_array = (struct My_structure *)((char *)shm_start + sizeof(int)); // 给数组元素赋值 for (int i = 0; i < array_len; i++) { snprintf(struct_array[i].my_text, sizeof(struct_array[i].my_text), "Text for element %d", i); snprintf(struct_array[i].my_name, sizeof(struct_array[i].my_name), "Name_%d", i); struct_array[i].my_number = i * 10; } // 数组式访问示例 printf("Element 2 - my_number: %d\n", struct_array[2].my_number); printf("Element 2 - my_name: %s\n", struct_array[2].my_name); // 卸载共享内存 if (shmdt(shm_start) == -1) { perror("shmdt failed"); exit(EXIT_FAILURE); } return 0; }
内容的提问来源于stack exchange,提问作者Firana M
相关产品推荐
相关产品推荐

