C语言中mmap映射文件如何按指定struct大小分块访问数据
解决方法
核心实现逻辑
你已经将mmap返回的地址强转为struct mapped *类型,C语言的指针算术会自动按照目标类型的大小做偏移,不需要手动计算字节数。你有3个连续的struct实例,直接通过数组下标或者指针偏移就能访问后面2个数据块:
data[0]对应第一个struct实例(你已经可以正常访问)data[1]对应第二个struct实例data[2]对应第三个struct实例
注意修复现有代码的问题
现有代码存在权限不匹配的隐患:你调用open时用了O_RDONLY只读权限,但mmap指定了PROT_READ | PROT_WRITE读写权限,运行时会触发mmap失败,需要根据你的使用场景调整:
- 如果需要修改映射数据:把open的flag改成
O_RDWR - 如果只需要读数据:把mmap的PROT参数改成
PROT_READ
另外建议添加以下校验逻辑避免运行错误:
- 检查mmap返回值是否为
MAP_FAILED,避免映射失败访问非法地址 - 校验文件大小是否等于
3 * sizeof(struct mapped),避免文件大小不符合预期导致越界访问 - 确保struct没有内存对齐填充,和文件块布局完全一致,可以给struct添加
__attribute__((packed))编译器属性(GCC/Clang环境下)避免自动对齐插入的填充字节。
修改后的完整代码示例
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> #include <sys/types.h> #include <stdbool.h> // 加packed避免结构体自动填充,确保大小为128字节 struct __attribute__((packed)) mapped { /* 在这里填写你的结构体字段,确保总大小128字节 */ }; int main (int argc, char **argv){ // 如果不需要写,保持O_RDONLY即可,后面mmap权限对应修改 int fd = open("file", O_RDWR, S_IRUSR | S_IWUSR); if (fd == -1) { perror("open file failed"); exit(EXIT_FAILURE); } struct stat st; if(fstat(fd, &st) == -1) { perror("get file stat failed"); close(fd); exit(EXIT_FAILURE); } // 校验文件大小是否符合预期 if (st.st_size != 3 * sizeof(struct mapped)) { fprintf(stderr, "file size mismatch, expected %zu, got %lld\n", 3 * sizeof(struct mapped), (long long)st.st_size); close(fd); exit(EXIT_FAILURE); } struct mapped *data = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (data == MAP_FAILED) { perror("mmap failed"); close(fd); exit(EXIT_FAILURE); } printf("File size: %lld\n", (long long)st.st_size); printf("struct mapped size: %zu\n", sizeof(struct mapped)); printf("Total struct count: %zu\n", st.st_size / sizeof(struct mapped)); // 遍历访问所有3个struct实例 for (int i = 0; i < 3; i++) { printf("\n===== struct %d content =====\n", i); // 这里替换为你自己的打印逻辑,比如printf("%d\n", data[i].xxx); } close(fd); munmap(data, st.st_size); exit(EXIT_SUCCESS); }
内容的提问来源于stack exchange,提问作者mello_
相关产品推荐
相关产品推荐

