![](/img/trans.png)
[英]If I have only the physical address of device buffer (PCIe), how can I map this buffer to user-space?
[英]How to find the physical address of a variable from user-space in Linux?
我想找到在用戶空間進程中定義的變量的物理地址? 有沒有辦法使用root權限來做到這一點?
正如之前部分回答的那樣,普通程序不需要擔心物理地址,因為它們在虛擬地址空間中運行並具有所有便利性。 此外,並非每個虛擬地址都有物理地址,它們可能屬於映射文件或交換頁面。 然而,有時看到這個映射可能會很有趣,即使是在用戶空間。
為此,Linux 內核通過/proc
中的一組文件將其映射公開給用戶空間。 文檔可以在這里找到。 簡短的摘要:
/proc/$pid/maps
提供了虛擬地址的映射列表以及附加信息,例如映射文件的相應文件。/proc/$pid/pagemap
提供有關每個映射頁面的更多信息,包括物理地址(如果存在)。這個網站提供了一個 C 程序,它使用這個接口轉儲所有正在運行的進程的映射,並解釋它的作用。
#include "stdio.h"
#include "unistd.h"
#include "inttypes.h"
uintptr_t vtop(uintptr_t vaddr) {
FILE *pagemap;
intptr_t paddr = 0;
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));
}
}
}
fclose(pagemap);
}
return paddr;
}
首先,你為什么要這樣做? 現代 VM 系統的目的是將應用程序程序員從物理內存布局的復雜性中移除。 給他們每個人自己統一的地址空間,讓他們的生活更輕松。
如果您確實想這樣做,您幾乎肯定需要使用內核模塊。 以正常方式獲取變量的虛擬地址,使用它來索引進程頁表並讀取您找到的值(幀的物理地址)。 然后加上頁偏移量,得到完整的物理地址。 請注意,啟用分頁時您將無法使用此地址。
(如果幸運的話,您可以從 /proc 文件系統中獲取 VM 區域的幀地址,因此不需要編寫內核模塊。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.