首先我们先要了解以下了解以下几种地址
物理地址:是真实存在的RAM的具体存储单元地址
逻辑地址:由于x86自80838以来出现的分段内存管理方式,操作系统将内存分为若干个段,各个段的起始地址(段基址)由CS,DS,SS,ES,我们平时的程序对变量取的地址叫作段内偏移地址,也就是逻辑地址。
线性地址:线性地址的组成为段基址<<4+逻辑地址(一般情况),线性地址就是存在于虚拟地址空间上的地址,又称为虚拟地址。
接下来我们需要了解一下pagemap文件,pagemap文件是每个进程私有的虚拟页到物理页的映射情况,每个pagemap项由8个字节64bit组成。格式如下
/proc/pid/pagemap:这个文件允许一个用户态的进程查看到每个虚拟页映射到的物理页,每一个虚拟页都包含了一个64位的值,信息如下:
Bits 0-54: page frame number(PFN) if present
Bits 0-4: swap type if swapped
Bits 5-54: swap offset if swapped
Bits 55-60:page shift
Bit 61: reserved ofr future use
Bit 62: page swapped
Bit 63: page present
如果这个page是在swap状态,然后PFN包含一个编码的交换文件号码,再将页的offset值写入swap中。没有映射的页就返回一个null PFN。这样就可以精确判断一个page是映射的或是swap的,并且可以比较不同进程间的映射页。
我们可以利用/proc/pid/maps去判断内存中哪块区域是被映射的,然后通过llseek就可以跳过没有映射的区域。
有此,我们假设出入&a,则&a/4k=vir_index &a%4k=m_offset(物理页面内的偏移量),我们便写出了如下代码
接着我们需要跳过文件中的若干个item项,具体偏移多少呢?当然是vri_index*8
偏移到具体的项之后 我们需要读取现在偏移量上的值,读取8字节,使用uint64_t类型