使用结构指针访问mmap区域

时间:2011-06-19 20:21:27

标签: c mmap

如果我通过具有孔的结构类型的指针访问文件的存储器映射,则可能不会将结构元素映射到正确的数据。例如。

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>

typedef union{
    int a;
    char c[4];
}INT;

typedef struct{
    char type;
    INT data;
}RECORD;

int main(){
    int fd;
    RECORD *recPtr;
    fd = open("./f1", O_RDWR);
    if (fd == -1){
            printf("Open Failed!\n");
    }
    printf("Size of RECORD: %d\n", sizeof(RECORD));
    recPtr = (RECORD *)mmap(0, 2*sizeof(RECORD), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (recPtr == MAP_FAILED){
            printf("Map Filaed!\n");
    }
    printf("type: %c, data: %c%c%c%c\n", recPtr->type, recPtr->data.c[0], recPtr->data.c[1], recPtr->data.c[2], recPtr->data.c[3]);
}

如果文件“f1”包含以下数据:

012345678

上述程序将输出显示为

Size of RECORD: 8
type: 0, data: 4567

因为字符123被结构孔吃掉了。

有没有办法在不使用pragma pack指令且不改变结构中元素的顺序的情况下避免这种情况。

2 个答案:

答案 0 :(得分:2)

您基本上有以下选择:

  1. 接受填充。只要您的数据不需要跨架构移植,这很好(也是最快的选择)。
  2. 使用__attribute__((packed))或类似命令来控制编译器插入的填充(推荐,但要求您使用编译器扩展)
  3. 在字节级别手动访问,不使用结构。例如:

    char type;
    int data;
    
    memcpy(&type, ((char *)recPtr), 1);
    memcpy(&data, ((char *)recPtr) + 1, sizeof(data));
    

答案 1 :(得分:1)

直接将二进制数据读入结构是一种灾难。这意味着你在没有验证的情况下对某些输入的结构做出假设;当然,您可以在事后检查结构的完整性。但通常情况下,您必须对输入数据进行体系结构相关调整。想想低端与大端。不同的字长,包装规则等

长话短说:不要为了黑暗的一面而堕落,这是诱惑快速黑客的承诺。

读取文件的唯一正确方法是用八位字节读取八位字节;您当然可以在缓冲区中读取更大的块,但是您应该通过查看每个位来处理它们。如果您担心性能问题,您应该阅读第1卷以及“计算机编程艺术”第4卷的内容,深入解释了如何有效地处理数据流而不忽略任何数据。

或使用Google的协议缓冲区。