将文件映射到内存并进行读写索引

问题描述:

我试图通过映射一个1 MiB文件(对应于RAM大小)来建模一个基本CPU。我想读/写这个文件。我的困惑是,我想我可以只是mmap我的文件,然后索引到内存块,就好像它是一个数组。我在网上看到了几个例子,这些例子都做得很好。例如,给出以下代码片段:将文件映射到内存并进行读写索引

int16_t ramD; 
if ((ramD = open("ramMap.txt", O_RDWR | O_CREAT, 1)) == -1) 
{ 
    errx(EX_OSERR, "RAM could not be initialized"); 
} 
uint16_t* ram = mmap(0, ram_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, ramD, 0); 

如何访问此mmapped文件中的特定位置以进行读写?我认为它会像ram[36]一样简单,它可以让我访问由mmap返回的指针的第36个字节的偏移量,但似乎并非如此。为了测试,我做了一个printf("%p\n", (void *) &ram);来查看mmap指向哪个地址给了我0x7fffffffde18(顺便说一句,它与我指定的mmap参数0无关)。同时,printf("%p\n", (void *) &ram[36])返回0x7ffff7ee1048

是否mmap不给我线性块内存?我在这里错过了什么?

+2

你不能把数组(或任何东西)地址'0'的。 'mmap'上的文档 说:“如果addr为NULL,则内核选择创建映射的地址;”。另一个问题是,你似乎打算通过指向'uint16_t'的指针读取字节(这可能是2字节)。 –

+1

'printf(“%p \ n”,(void *)&ram);''这里你打印'ram'变量的地址,可能是从打印地址分配到堆栈上的,你可能想'printf(“%p \ n“,(void *)ram);'。 –

+1

如果将基地址存储在'uint16_t *'中,则'ram [36]'在偏移量72和73处寻址字节,而不是字节36,是单位大小的倍数,如果它是一个'int'的数组,那么必须编写'array_of_int [offset * sizeof(int)]'来获得偏移量的整数会很麻烦。 '不会让你这么做;你写'array_of_int [offset]'得到整数。类似的注释适用于'uint16_t *'。 –

printf("%p\n", (void *) &ram); 

让你在堆栈上的局部变量ram的地址。你想

printf("%p\n", (void *)ram); 

得到您映射的ram地址。此外,由于您将ram声明为uint16_t,ram[36]将是存储器的16位字(字节72和73)的第36位。


从0开始计数当然

+0

谢谢,这清理了很多。但仍然是一个问题:我得到'0x7ffff7ee1000'从'printf(“%p \ n”,(void *)ram)'',但是当我尝试通过'printf(“%p \ n”,(void *)&ram获得'ram [36]'的地址[36]),我得到了'0x7ffff7ee1024'。仍然不是我期待的。这是将内存的类型更改为uint8_t *之后。 – Davigor

+0

@DavidMcGee:如果指针是'uint8_t *',那么基地址'ram = 0x7FFFF7EE1000'就意味着'&ram [36]'应该是'0x7FFFF7EE1024'(因为十六进制24 = == dec 36)。 –

+0

啊对,傻傻的疏忽。感谢所有的帮助。 – Davigor