Linux中是否有用于从虚拟地址确定物理地址的API?
Linux操作系统中是否有用于从虚拟地址确定物理地址的API?内核和用户空间使用由内存管理硬件映射到物理地址的虚拟地址(也称为线性地址)。此映射由操作系统设置的页表定义 DMA设备使用总线地址。在i386 PC上,总线地址与物理地址相同,但其他体系结构可能具有特殊的地址映射硬件,用于将总线地址转换为物理地址 在Linux中,您可以从Linux中是否有用于从虚拟地址确定物理地址的API?,linux,memory,memory-management,linux-kernel,virtual-address-space,Linux,Memory,Memory Management,Linux Kernel,Virtual Address Space,Linux操作系统中是否有用于从虚拟地址确定物理地址的API?内核和用户空间使用由内存管理硬件映射到物理地址的虚拟地址(也称为线性地址)。此映射由操作系统设置的页表定义 DMA设备使用总线地址。在i386 PC上,总线地址与物理地址相同,但其他体系结构可能具有特殊的地址映射硬件,用于将总线地址转换为物理地址 在Linux中,您可以从asm/io.h使用这些函数: 虚拟物理(虚拟地址) 物理地址 虚拟至虚拟总线(虚拟地址) 总线到虚拟(总线地址) 所有这些都是关于访问普通内存的。PCI或ISA
asm/io.h
使用这些函数:
- 虚拟物理(虚拟地址)李>
- 物理地址李>
- 虚拟至虚拟总线(虚拟地址)李>
- 总线到虚拟(总线地址)李>
至于用户land API,我所知不存在任何问题。如前所述,普通程序不需要担心物理地址,因为它们在虚拟地址空间中运行,非常方便。此外,并非每个虚拟地址都有物理地址,这些地址可能属于映射文件或交换的页面。然而,有时看到这种映射可能会很有趣,即使是在userland中 为此,Linux内核通过
/proc
中的一组文件公开其到userland的映射。可以找到文档。小结:
/proc/$pid/maps
提供虚拟地址映射列表以及其他信息,例如映射文件的对应文件/proc/$pid/pagemap
提供有关每个映射页面的更多信息,包括物理地址(如果存在)/proc//pagemap
userland最小可运行示例
virt_to_phys_user.c
定义源代码700
#包括/*开放*/
#包括/*uint64\u t*/
#包括/*printf*/
#包括/*尺寸*/
#include/*pread,sysconf*/
类型定义结构{
uint64_t pfn:55;
无符号整数软_脏:1;
未签名的整数文件\u页:1;
未签名整数交换:1;
无符号整数:1;
}页面地图输入;
/*解析给定虚拟地址的pagemap条目。
*
*@param[out]entry解析后的条目
*@param[in]pagemap_fd文件描述符到打开的/proc/pid/pagemap文件
*@param[in]vaddr虚拟地址以获取条目
*@成功返回0,失败返回1
*/
int pagemap\u get\u条目(PagemapEntry*entry,int pagemap\u fd,UINTPTTR\u vaddr)
{
尺寸(单位:nread);
ssize_t ret;
uint64_t数据;
uintptr\t vpn;
vpn=vaddr/sysconf(\u SC\u PAGE\u SIZE);
nread=0;
而(nread>55)和1;
条目->文件页面=(数据>>61)&1;
条目->交换=(数据>>62)&1;
输入->当前=(数据>>63)&1;
返回0;
}
/*使用/proc/PID/pagemap将给定的虚拟地址转换为物理地址。
*
*@param[out]paddr物理地址
*@param[in]要转换为的pid进程
*@param[in]vaddr虚拟地址以获取条目
*@成功返回0,失败返回1
*/
int virt_to_phys_用户(uintpttr_t*paddr、pid_t pid、uintptpr_t vaddr)
{
char pagemap_文件[BUFSIZ];
int pagemap_fd;
snprintf(pagemap_文件,sizeof(pagemap_文件),“/proc/%ju/pagemap”,(uintmax_t)pid);
pagemap_fd=打开(仅pagemap_文件);
如果(pagemap_fd<0){
返回1;
}
页面地图输入;
if(pagemap\u get\u条目(&entry,pagemap\u fd,vaddr)){
返回1;
}
关闭(pagemap_fd);
*paddr=(entry.pfn*sysconf(_SC_PAGE_SIZE))+(vaddr%sysconf(_SC_PAGE_SIZE));
返回0;
}
int main(int argc,字符**argv)
{
pid_t pid;
uintpttr_t vaddr,paddr=0;
如果(argc<3){
printf(“用法:%s pid vaddr\n”,argv[0]);
返回退出失败;
}
pid=strtoull(argv[1],NULL,0);
vaddr=strtoull(argv[2],NULL,0);
if(虚拟至物理用户(&paddr、pid、vaddr)){
fprintf(stderr,“错误:virt_to_phys_user\n”);
返回退出失败;
};
printf(“0x%jx\n”,(uintmax\u t)paddr);
返回退出成功;
}
用法:
sudo./virt\u to\u phys\u user.out
sudo
必须读取/proc//pagemap
,即使您拥有文件权限,如以下所述:
作为承诺
vaddr 0x600800
pid 110