我需要使用C中的/proc/pid/maps和/proc/pid/pagemap接口以编程方式计算Linux中给定进程的总页表大小。
我现在如何获得一个页面条目和计算的页面框架号码使用这些接口。但我不知道如何计算表的大小给出了这些信息。
下面是我的代码:
void alltablesize(int pid) {
//open /proc/pid/maps to read virtual addresses
char file_path[50];
sprintf(file_path, MAPS_FILE, pid);
FILE *maps = fopen(file_path, "r");
if(maps == NULL) {
perror("Failed to open /proc/pid/maps");
return;
}
char line[256];
uint64_t start, end;
uint64_t vpn, pfn;
uint64_t num_entries;
uint64_t total_page_size;
while(fgets(line, sizeof(line), maps) != NULL) {
char fname[256];
sscanf(line, "%lx-%lx %*s %*lx %*x:%*x %*d %s", &start, &end, fname);
for(vpn = start/PAGE_SIZE; vpn < end/PAGE_SIZE; vpn++) {
//open 7proc/pid/pagemap to extract information about the va
char pagemap_path[50];
sprintf(pagemap_path, PAGEMAP_FILE, pid);
int pagemap_fd = open(pagemap_path, O_RDONLY);
if (pagemap_fd == -1) {
perror("Failed to open /proc/pid/pagemap");
fclose(maps);
return;
}
uint64_t entry; //entry is 64 bits
off_t offset = vpn * PAGEMAP_LENGTH;
lseek(pagemap_fd, offset, SEEK_SET);
read(pagemap_fd, &entry, sizeof(uint64_t));
pfn = get_pfn(entry);
num_entries++;
}
}
}
1条答案
按热度按时间gkl3eglg1#
回想一下,地址是由以下各项分解的:
如果页面有效(即存在于最后一级索引中),则必须在它上面的每个级别中都有一个页面。因此,一页内存将需要4页页页表。然而,如果它们的虚拟地址在位21..63中匹配,则可以有多达512 [12..20]个页共享页表的这4个页。
这递归地应用;因此在页表每一级上,在必须向上一级添加新页之前,最多可以有512个连续条目。
这意味着您需要按地址处理Map,并重新构造这些索引,以确定需要多少个索引。
一个额外的复杂性是大页面。例如,我可以有一个2 M(512 * 4096)的大页面,而不是一个“最后一级页表”,这样就可以跳过最后一个。还有1G的大页面,覆盖了“倒数第二层页表”。