我正在尝试编写一个Linux程序来检查进程的脏内存页。
我在Linux-4.18.20中使用/proc/kpageflags,其中第4位是页面的脏标志。
下面的代码是映射一个文件并写入其中的一部分,使这些页面变脏,如下所示
if (fd >= 0) {
vaddr = mmap(0, 0x10000, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (vaddr != (void *) -1) {
printf("mmaped address at %pn", vaddr);
for (i = 0; i < 0x10000; i ++) {
c = vaddr[i]; /// Load file into memory page, clean.
}
for (i = 0; i < 0x2000; i ++) {
vaddr[i] = 'a'; /// Write memory page make it dirty.
}
}
}
从/proc/pid/smaps中,我得到了我所期望的如下内容,
7f1a497db000-7f1a497eb000 rw-p 00000000 08:11 4741474 /mnt/test/process/dumpfile
Size: 64 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 64 kB
Pss: 64 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 56 kB <<<=
Private_Dirty: 8 kB <<<-
Referenced: 64 kB
Anonymous: 8 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kB
VmFlags: rd wr mr mw me ac sd
其中56kB是干净的,8kB是脏的。
但是通过读取/proc/pid/pagemap和/proc/kpageflags,相应的页面没有设置"脏"位,即页面标志如下,
0x7f1a497db000 : pfn 3de54e pageflags are 5868
0x7f1a497dc000 : pfn 3de834 pageflags are 5868
0x7f1a497dd000 : pfn 3cc920 pageflags are 80000082c
0x7f1a497de000 : pfn 3c970b pageflags are 80000082c
0x7f1a497df000 : pfn 3bf8e9 pageflags are 80000082c
0x7f1a497e0000 : pfn 3c14f8 pageflags are 80000082c
0x7f1a497e1000 : pfn 3ccef4 pageflags are 80000082c
0x7f1a497e2000 : pfn 3ccef5 pageflags are 80000082c
0x7f1a497e3000 : pfn 3cc4e8 pageflags are 80000082c
0x7f1a497e4000 : pfn 3cc4e9 pageflags are 80000082c
0x7f1a497e5000 : pfn 3cced0 pageflags are 80000082c
0x7f1a497e6000 : pfn 3cced1 pageflags are 80000082c
0x7f1a497e7000 : pfn 3cc158 pageflags are 80000082c
0x7f1a497e8000 : pfn 3cc159 pageflags are 80000082c
0x7f1a497e9000 : pfn 3cc456 pageflags are 80000082c
0x7f1a497ea000 : pfn 3cc457 pageflags are 80000082c
Bit 4不是'1' !
我的测试有什么问题吗?
或者有没有其他方法来读取/知道进程的Vaddr/Phyaddr是否脏?
通过阅读Linux代码,我得到了答案。
/proc/pid/smaps输出使用来自pte和page结构体的标志。在上面的例子中,dirty位设置在pte中,而不是在page struct中,所以smaps也会将该页计算为"dirty"。
但是/proc/kpageflags只计算页面结构中的标志,其中'dirty'在上面的情况下没有设置,这意味着页面是'clean'。