使用 mmap() 读取二进制文件

reading a binary file with mmap()

您能解释一下为什么我的程序会从文件中读取奇怪的值吗?我正在尝试使用 mmap 读取文件。我使用这个函数的原因是为了了解它是如何工作的。然后我将它与 /dev/mem 一起使用,以读取特定物理内存地址处的二进制数据。

我使用以下 python 脚本创建了一个文件 'hello1.raw'。

fd = open("hello1.raw", "w+b")
fd.write(b'01')

fd.close()

然后我尝试使用下面的c程序读取它。

#include <stdio.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(){

int fd = open("hello1.raw",O_RDWR);

struct stat st;
fstat(fd, &st);
size_t size=st.st_size;

int * a = mmap(0, size, PROT_READ|PROT_EXEC ,MAP_SHARED , fd, 0);
printf("address of hello1.raw: %p\n",a); 
printf("data in hello1.raw: %d\n", *a);

int b = munmap(a, size);
close(fd);

return 0;
}

但是这个程序打印出奇怪的值。

address of hello.raw: 0x10238d000
data in hello.raw: 12592

数据不是01而是12592。

#include <stdio.h>
#include <sys/stat.h>

#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(){

int fd, rc , ii;
int *ptr;
struct stat st;
size_t size;

fd = open("hello1.raw", O_RDWR);

rc = fstat(fd, &st);
fprintf(stderr, "stat() = %d\n", rc);
size=st.st_size;
fprintf(stderr, "size=%zu\n", size);

ptr = mmap(0, size, PROT_READ|PROT_EXEC ,MAP_SHARED , fd, 0);
fprintf(stderr, "address of hello1.raw: %p\n", ptr);

for (ii=0; ii < size/sizeof *ptr; ii++) {
   printf("data in raw[%d]: %d\n", ii, ptr[ii]);
        }

rc = munmap(ptr, size);
fprintf(stderr, "unmap() = %d\n", rc);
close(fd);

return 0;
}

  • 首先:检查系统调用的 return 值并向标准错误报告。
  • 其次:mmap() 适用于页面。如果 st.st_size 不是页面大小的倍数,则向上舍入。 (Linux 用零填充其余部分)
  • 通过将 "OMG\n" 放入 hello1.raw 文件(4 字节)和 运行 程序进行测试。
  • 现在删除一个字符)eg -->> "OM\n") end re运行 the program.

结果 1:

$ ./a.out
stat() = 0
size=4
address of hello1.raw: 0xa64000
data in raw[0]: 172445007
unmap() = 0

结果 2:

$ ./a.out
stat() = 0
size=3
address of hello1.raw: 0xe37000
unmap() = 0

解释:第一个运行文件大小为4,mmap成功,打印int。 (sizeof int 为 4)。 在第二种情况下,mmap 成功,但不会打印 int(我的循环版本拒绝引用超出 eof 的映射内存)如果你 would 允许引用超出 eof 的高位字节(假设 Big endian here) 的 int 值将显示为零,因为系统用零填充了页面。

如果你想看nul-padding的效果,把for-loop改成for (ii=0; ii <= size/sizeof *ptr; ii++) {然后重复上面的实验。