v2phy示例
#include <sys/user.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
uint64_t virt2phy(const void *addr)
{
int fd, ret;
unsigned long virt_pfn;
off_t offset;
uint64_t page, phy_addr;
fd = open("/proc/self/pagemap", O_RDONLY);
if (fd < 0) {
printf("Cannot open file /proc/self/pagemap\n");
return -1;
}
virt_pfn = (uint64_t)addr / PAGE_SIZE;
/* /proc/self/pagemap 8个字节为一个page页索引 */
offset = sizeof(uint64_t) * virt_pfn;
if (lseek(fd, offset, SEEK_SET) < 0) {
printf("lseek failed\n");
return -1;
}
ret = read(fd, &page, sizeof(uint64_t));
close(fd);
/*
* the pfn (page frame number) are bits 0-54 (see pagemap.txt in linux Documentation)
*/
if ((page & 0x7fffffffffffffULL) == 0) {
printf("get page failed\n");
return -1;
}
phy_addr = (page & 0x7fffffffffffffULL) * PAGE_SIZE + ((uint64_t)addr % PAGE_SIZE);
return phy_addr;
}
int main(void)
{
uint8_t *p = malloc(1024 * 1024);
*(p + 4096) = 10;
printf("virt:%p phys:%p\n", p + 4096, virt2phy(p + 4096));
*(p + 2 * 4096) = 10;
printf("virt:%p phys:%p\n", p + 2 * 4096, virt2phy(p + 2 * 4096));
return 0;
}
dpdk提供了virt2phy的方法,可以直接使用rte_mem_virt2phy实现虚拟地址到物理地址的转换。
补充:linux用户态获取page_size的方法
- 法一: 保含
#include <sys/user.h>头文件,使用PAGE_SIZE宏
#include <stdio.h>
#include <sys/user.h>
int main(void)
{
printf("page_size = %ld\n", PAGE_SIZE);
return 0;
}
- 法二: 包含
#include <unistd.h>,使用getpagesize函数
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int page_size = getpagesize();
printf("page_size = %d\n", page_size);
return 0;
}