用偏移量写入mmap文件,可能处理字节序

时间:2014-12-09 14:23:02

标签: c++ mmap endianness

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

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; // + \0 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

我怀疑这与endianess有关。我尝试了以下方法:

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

return htonl(*((int *)(mapBuffer + index*sizeof(int))); //for getItem

getItem始终返回0.

有什么建议吗?感谢。

2 个答案:

答案 0 :(得分:4)

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

类似

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

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

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

答案 1 :(得分:2)

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