使用 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++) {
然后重复上面的实验。
您能解释一下为什么我的程序会从文件中读取奇怪的值吗?我正在尝试使用 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++) {
然后重复上面的实验。