为什么映射值的物理地址始终为零?
why is the physical address of a mmap value is aways zero?
我编写了一个程序来计算给定虚拟地址的物理地址。该程序始终 return 0。这意味着未找到特定页面。为什么该页面不可用?
此代码的作用是:此代码创建一个文件内存,并使用我从 中获取的函数将该内存映射虚拟地址转换为物理地址。
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h> // O_RDONLY
//#include <stddef.h> // to get NULL definition. NULL not a built in const.
#include <string.h> // NULL is also defined in string.h, stdlib.h
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include "inttypes.h"
uint64_t vtop(uint64_t vaddr) {
FILE *pagemap;
uint64_t paddr = 0;
unsigned long long int offset = (vaddr / sysconf(_SC_PAGESIZE)) * sizeof(uint64_t);
uint64_t e;
// https://www.kernel.org/doc/Documentation/vm/pagemap.txt
if ((pagemap = fopen("/proc/self/pagemap", "r"))) {
if (lseek(fileno(pagemap), offset, SEEK_SET) == offset) {
if (fread(&e, sizeof(uint64_t), 1, pagemap)) {
if (e & (1ULL << 63)) { // page present ?
paddr = e & ((1ULL << 54) - 1); // pfn mask
paddr = paddr * sysconf(_SC_PAGESIZE);
// add offset within page
paddr = paddr | (vaddr & (sysconf(_SC_PAGESIZE) - 1));
printf(" paddr %lu \n", paddr);
}
else {
printf("page not found\n");
}
}
}
fclose(pagemap);
}
return paddr;
}
int main() {
int oflag = O_RDONLY;
const char *path = "file.json";
const int fd = open(path, oflag);
// use stat to find the file size
struct stat stat;
int ret = fstat(fd, &stat);
int mflags = MAP_PRIVATE; // information about handling the mapped data
int mprot = PROT_READ|PROT_WRITE; // access permissions to the data being mapped
size_t size = stat.st_size;
void *addr = mmap(NULL, size, mprot, mflags, fd, 0);
printf("virtual addres is %p\n", addr);
printf("physical addres is %ld\n", vtop((uint64_t)addr));
return 0;
}
当我使用 malloc 而不是 mmap 时,我得到的物理地址是 0x670
这个数字有什么特点?
I wrote a program which calculates the physical address of a given
virtual address. This program always return 0.
从/proc/self/pagemap
访问物理地址需要运行具有root权限的程序(sudo
)。否则,您仍然可以打开 /proc/self/pagemap
并从中读取内容。只是物理地址看起来都为零。由于您将 NULL
传递给 mmap
的第一个参数,它将 return 一个页面对齐的虚拟地址。所以页面偏移量也为零。因此,vtop
将 return 归零。
When I use malloc, instead of mmap, I get the physical address as
0x670what is the speciality of this number?
使用 malloc
分配内存时,returned 虚拟地址可能不是页面对齐的。因此,页面偏移量可能不为零。正在打印的值 0x670
只是添加到零物理地址的页面偏移量。
这是您需要做的:
- 确保传递给
mmap
的长度参数(文件大小)大于零(文件不能为空)。否则,mmap
returns -1 with errno
设置为 EINVAL
.
- 无论程序是否有root权限,如果none个映射页面被触及,默认情况下,不会为它们分配物理页面。该程序将打印
page not found
。为避免此问题,您可以在调用 vtop
. 之前读取一个字节 (char c = *((char*)addr);
)
- 现在如果你触及映射区域的第一页,但运行程序没有root权限,物理地址将为零但页面偏移量可能为零也可能不为零。所以你只会得到页面偏移量。 运行 带有
sudo
的程序可以解决问题。
我编写了一个程序来计算给定虚拟地址的物理地址。该程序始终 return 0。这意味着未找到特定页面。为什么该页面不可用?
此代码的作用是:此代码创建一个文件内存,并使用我从 中获取的函数将该内存映射虚拟地址转换为物理地址。
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h> // O_RDONLY
//#include <stddef.h> // to get NULL definition. NULL not a built in const.
#include <string.h> // NULL is also defined in string.h, stdlib.h
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include "inttypes.h"
uint64_t vtop(uint64_t vaddr) {
FILE *pagemap;
uint64_t paddr = 0;
unsigned long long int offset = (vaddr / sysconf(_SC_PAGESIZE)) * sizeof(uint64_t);
uint64_t e;
// https://www.kernel.org/doc/Documentation/vm/pagemap.txt
if ((pagemap = fopen("/proc/self/pagemap", "r"))) {
if (lseek(fileno(pagemap), offset, SEEK_SET) == offset) {
if (fread(&e, sizeof(uint64_t), 1, pagemap)) {
if (e & (1ULL << 63)) { // page present ?
paddr = e & ((1ULL << 54) - 1); // pfn mask
paddr = paddr * sysconf(_SC_PAGESIZE);
// add offset within page
paddr = paddr | (vaddr & (sysconf(_SC_PAGESIZE) - 1));
printf(" paddr %lu \n", paddr);
}
else {
printf("page not found\n");
}
}
}
fclose(pagemap);
}
return paddr;
}
int main() {
int oflag = O_RDONLY;
const char *path = "file.json";
const int fd = open(path, oflag);
// use stat to find the file size
struct stat stat;
int ret = fstat(fd, &stat);
int mflags = MAP_PRIVATE; // information about handling the mapped data
int mprot = PROT_READ|PROT_WRITE; // access permissions to the data being mapped
size_t size = stat.st_size;
void *addr = mmap(NULL, size, mprot, mflags, fd, 0);
printf("virtual addres is %p\n", addr);
printf("physical addres is %ld\n", vtop((uint64_t)addr));
return 0;
}
当我使用 malloc 而不是 mmap 时,我得到的物理地址是 0x670
这个数字有什么特点?
I wrote a program which calculates the physical address of a given virtual address. This program always return 0.
从/proc/self/pagemap
访问物理地址需要运行具有root权限的程序(sudo
)。否则,您仍然可以打开 /proc/self/pagemap
并从中读取内容。只是物理地址看起来都为零。由于您将 NULL
传递给 mmap
的第一个参数,它将 return 一个页面对齐的虚拟地址。所以页面偏移量也为零。因此,vtop
将 return 归零。
When I use malloc, instead of mmap, I get the physical address as 0x670what is the speciality of this number?
使用 malloc
分配内存时,returned 虚拟地址可能不是页面对齐的。因此,页面偏移量可能不为零。正在打印的值 0x670
只是添加到零物理地址的页面偏移量。
这是您需要做的:
- 确保传递给
mmap
的长度参数(文件大小)大于零(文件不能为空)。否则,mmap
returns -1 witherrno
设置为EINVAL
. - 无论程序是否有root权限,如果none个映射页面被触及,默认情况下,不会为它们分配物理页面。该程序将打印
page not found
。为避免此问题,您可以在调用vtop
. 之前读取一个字节 ( - 现在如果你触及映射区域的第一页,但运行程序没有root权限,物理地址将为零但页面偏移量可能为零也可能不为零。所以你只会得到页面偏移量。 运行 带有
sudo
的程序可以解决问题。
char c = *((char*)addr);
)