
Таким образом, если n процессов совместно используют библиотеку L размером M, то вклад в их PSS равен M/n.
Теперь представьте, что один из процессов завершается. Тогда вклад будет M/(n-1).
В1: Мой вопрос: как скоро это изменение отразится на значениях PSS процессов, которые все еще работают и используют общую библиотеку?
Q2: В качестве тривиального случая предположим, что только два процесса используют общую библиотеку L размером 100 КБ. Вклад PSS в каждый процесс составляет 50 КБ. Теперь, когда P2 умирает, это единственный процесс, использующий L. Поэтому его PSS должен увеличиться и стать 100 КБ. Как скоро это произойдет, как только 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
сам по себе накапливает информацию в 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 «всегда актуален».