使用偏移量写入 mmap 文件,可能处理 endianess

Writing to mmap file with an offset, possibly dealing with endianess

本文关键字:处理 endianess 文件 mmap 偏移量      更新时间:2023-10-16

我正在实现一个函数,该函数写入给定偏移量的内存映射文件。代码的极简解释如下:

MappedFile::MappedFile(int numOfItems, char * fname){
    pageSize = sysconf(_SC_PAGE_SIZE);
    fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
    // Stretch the file size to the size of the (mmapped) array
    size_t newsize = numOfItems*sizeof(int) + 1; // +  null character
    if (lseek(fd, newsize-1, SEEK_SET) == -1)
    {
        //below is not good practice. See comment for explanation.
        close(fd);
        perror("Error calling lseek() to 'stretch' the file");
        exit(EXIT_FAILURE);
    }
    if (write(fd, "", 1) == -1)
    {
        close(fd);
        perror("Error writing last byte of the file");
        exit(EXIT_FAILURE);
    }
    if((mapBuffer = (char *)mmap(NULL, sizeof(int) * numOfItems, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED){
        perror("Error mapping file");
        exit(0);
    }
}
void MappedFile::setItem(int index, int value){
    //have problem here
    mapBuffer[index*sizeof(int)] = value;
}
int MappedFile::getItem(int index){
    return *((int *)(mapBuffer + index*sizeof(int));
}

该类将大量整数映射到二进制文件中。问题setItemgetItem并不总是设置/获取相同的值。例如:

MappedFile intarr(2000, "Test.bin");
intarr.setItem(5, 220);
cout << intarr.getItem(5) << endl;

将打印220 .然而

MappedFile intarr(2000, "Test.bin");
intarr.setItem(5, 2200);
cout << intarr.getItem(5) << endl;

将打印152 .

我怀疑这与恩迪亚内在有关。我尝试了以下方法:

mapBuffer[index*sizeof(int)] = ntohl(value); //for setItem
return htonl(*((int *)(mapBuffer + index*sizeof(int))); //for getItem

getItem总是返回 0。

有什么建议吗?谢谢。

最大的问题是您将指向char的指针视为指向int的指针,而这些不是一回事。如果您希望映射的内存存储整数,请使用指向int的指针并使用正常的数组索引。

所以像

int* mapBuffer = static_cast<int*>(mmap(...));
mapBuffer[someIndex] = someIntValue;

更准确地说,以下赋值将截断整数以适应char

mapBuffer[index*sizeof(int)] = value;

mapBuffer 是一个字符* - 所以你只能将 int 的低 8 位写入它。 十六进制中的 2200 是 0x898,152 是0x98,因此您丢失了上字节。将指针升级到 int* 并从 get/set 中删除 *sizeof(int)。