【发布时间】:2023-02-10 14:25:27
【问题描述】:
linux 中的 smaps 和 smaps_rollup 有什么区别? 我不知道为什么 PSS 大小在所有进程中的 smaps 和 smaps_rollup 之和之间不同。 我想知道这些命令如何获得 PSS 大小。
【问题讨论】:
linux 中的 smaps 和 smaps_rollup 有什么区别? 我不知道为什么 PSS 大小在所有进程中的 smaps 和 smaps_rollup 之和之间不同。 我想知道这些命令如何获得 PSS 大小。
【问题讨论】:
当 Linux 内核计算 PSS(比例集大小)时,内核会在字节级别处理该值(实际上,内核会在更细粒度的级别计算 PSS。请参见下面的代码 sn-p.)。这是来自 smaps_account 和 /fs/proc/task_mmu.c 的代码 sn-p:
for (i = 0; i < nr; i++, page++) {
int mapcount = page_mapcount(page);
unsigned long pss = PAGE_SIZE << PSS_SHIFT;
if (mapcount >= 2)
pss /= mapcount;
smaps_page_accumulate(mss, page, PAGE_SIZE, pss, dirty, locked,
mapcount < 2);
}
如您所见,为计算每个页面的pss,内核在使用前将值除以页面的mapcount。因此,实际值可以用字节级表示。例如,如果一个页面由三个进程映射,则每个进程为该页面获得pss大小的 4KB/3(1365.333 字节)。
当用户请求打印/proc/<pid>/smaps时,内核为目标进程中的每个vma打印smaps,而/proc/<pid>/smaps_rollup打印smaps的总和。问题是,内核以 KB 为单位打印 /proc/<pid>/smaps(以及 /proc/<pid>/smaps_rollup)的值。这意味着 1KB 以下的 PSS 值将被丢弃。请参见下面的代码 sn-p。所有打印的值都右移 10。
#define SEQ_PUT_DEC(str, val)
seq_put_decimal_ull_width(m, str, (val) >> 10, 8)
/* Show the contents common for smaps and smaps_rollup */
static void __show_smap(struct seq_file *m, const struct mem_size_stats *mss,
bool rollup_mode)
{
SEQ_PUT_DEC("Rss: ", mss->resident);
SEQ_PUT_DEC(" kB
Pss: ", mss->pss >> PSS_SHIFT);
SEQ_PUT_DEC(" kB
Pss_Dirty: ", mss->pss_dirty >> PSS_SHIFT);
if (rollup_mode) {
/*
* These are meaningful only for smaps_rollup, otherwise two of
* them are zero, and the other one is the same as Pss.
*/
SEQ_PUT_DEC(" kB
Pss_Anon: ",
mss->pss_anon >> PSS_SHIFT);
SEQ_PUT_DEC(" kB
Pss_File: ",
mss->pss_file >> PSS_SHIFT);
SEQ_PUT_DEC(" kB
Pss_Shmem: ",
mss->pss_shmem >> PSS_SHIFT);
}
//...
对于/proc/<pid>/smaps_rollup,内核聚合vma的每个smaps中的值,包括丢弃的小于1KB的值,然后以KB为单位打印值。这就是为什么 smaps 中的 PSS 总和与 smaps_rollup 中的 PSS 值不同的原因。
【讨论】: