我正在实现一个函数,该函数在给定偏移量的情况下写入内存映射文件。 代码的极简主义解释如下:
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));
}
该类将大量整数映射到二进制文件中。问题是setItem
和getItem
并不总是设置/获得相同的值。例如:
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.
有什么建议吗?感谢。
答案 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)。