因此,如果 n 个进程共享大小为 M 的库 L,则对其 PSS 的贡献为 M/n。
现在想象其中一个进程终止。因此贡献将为 M/(n-1)。
问题 1:我的问题是,此更改多久会反映在仍在运行并使用共享库的进程的 PSS 值中?
Q2:作为一个简单的例子,假设只有两个进程正在使用大小为 100K 的共享库 L。 PSS对每个进程的贡献是50K。现在,当 P2 死亡时,它是唯一使用 L 的进程。因此它的 PSS 应该增加并变为 100K。这种情况多久会发生,是 P2 死亡后立即发生,还是一段时间后发生?过了多少时间?
答案1
更改会立即反映出来。一路上没有缓存。当您读取 时/proc/<pid>/smaps
,您实际上触发了对该进程页表的遍历。有关映射的信息会一路累积,然后显示,无需任何缓存。
文件背后的代码/proc/<pid>/smaps
位于 中fs/proc/task_mmu.c
,特别是show_smap
功能。
该函数执行walk_page_range
以下操作:smaps_pte_range
作为 PTE 回调。smaps_pte_range
本身将信息积累在 a 中struct mem_size_stats
。
该代码的部分负责PSS
:
mapcount = page_mapcount(page);
if (mapcount >= 2) {
if (pte_dirty(ptent) || PageDirty(page))
mss->shared_dirty += ptent_size;
else
mss->shared_clean += ptent_size;
mss->pss += (ptent_size << PSS_SHIFT) / mapcount;
} else {
if (pte_dirty(ptent) || PageDirty(page))
mss->private_dirty += ptent_size;
else
mss->private_clean += ptent_size;
mss->pss += (ptent_size << PSS_SHIFT);
}
Shared
(您可以在这里看到,如果页面实际上被多次映射,则只能在该部分中进行计算- 否则它被视为私有。)
page_mapcount
被内联定义linux/mm.h
并简单地访问struct page
:
static inline int page_mapcount(struct page *page)
{
return atomic_read(&(page)->_mapcount) + 1;
}
所以PSS“始终是最新的”。