我認爲statm
是一個近似的簡化smaps
,這是更昂貴的得到。我來到這個結論我看着源後:
smaps
你smaps
看到/fs/proc/task_mmu.c
定義的信息:
static int show_smap(struct seq_file *m, void *v, int is_pid)
{
(...)
struct mm_walk smaps_walk = {
.pmd_entry = smaps_pte_range,
.mm = vma->vm_mm,
.private = &mss,
};
memset(&mss, 0, sizeof mss);
walk_page_vma(vma, &smaps_walk);
show_map_vma(m, vma, is_pid);
seq_printf(m,
(...)
"Rss: %8lu kB\n"
(...)
mss.resident >> 10,
在/mm/pagewalk.c
定義的使用walk_page_vma
在mss
信息。然而,mss
成員resident
不填寫walk_page_vma
- 相反,walk_page_vma
調用回調smaps_walk
規定:
.pmd_entry = smaps_pte_range,
.private = &mss,
這樣的:
if (walk->pmd_entry)
err = walk->pmd_entry(pmd, addr, next, walk);
那麼什麼是我們的回調,smaps_pte_range
在/fs/proc/task_mmu.c
,做? 它在某些情況下調用smaps_pte_entry
和smaps_pmd_entry
,其中兩個都叫statm_account()
,反過來......升級resident
大小!所有這些功能都在已經鏈接的task_mmu.c
中定義,所以我沒有發佈相關的代碼片段,因爲它們可以在鏈接的源代碼中輕鬆查看。
PTE代表Page Table Entry,PMD是Page Middle Directory。所以基本上我們遍歷與給定進程相關聯的頁面條目並根據情況更新RAM使用情況。
statm
你statm
看到的信息在/fs/proc/array.c定義:
int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
{
unsigned long size = 0, resident = 0, shared = 0, text = 0, data = 0;
struct mm_struct *mm = get_task_mm(task);
if (mm) {
size = task_statm(mm, &shared, &text, &data, &resident);
mmput(mm);
}
seq_put_decimal_ull(m, 0, size);
seq_put_decimal_ull(m, ' ', resident);
seq_put_decimal_ull(m, ' ', shared);
seq_put_decimal_ull(m, ' ', text);
seq_put_decimal_ull(m, ' ', 0);
seq_put_decimal_ull(m, ' ', data);
seq_put_decimal_ull(m, ' ', 0);
seq_putc(m, '\n');
return 0;
}
這一次,resident
由task_statm
填補。這個有兩個實現,一個在/fs/proc/task_mmu.c
,另一個在/fs/proc/task_nomm.c
。由於它們幾乎肯定是互斥的,因此我將重點介紹task_mmu.c
(其中還包含task_smaps
)中的實現。在此實現,我們看到
unsigned long task_statm(struct mm_struct *mm,
unsigned long *shared, unsigned long *text,
unsigned long *data, unsigned long *resident)
{
*shared = get_mm_counter(mm, MM_FILEPAGES);
(...)
*resident = *shared + get_mm_counter(mm, MM_ANONPAGES);
return mm->total_vm;
}
它查詢一些櫃檯,即MM_FILEPAGES
和MM_ANONPAGES
。這些計數器在內存上的不同操作期間被修改,例如在/mm/memory.c
處定義的do_wp_page
。所有的修改似乎都是通過位於/mm/
的文件完成的,而且似乎有相當多的修改,所以我沒有在這裏包括它們。
結論
smaps
並通過所有被引用的內存區域和更新resident
大小使用收集到的信息複雜的迭代。 statm
使用已由其他人計算的數據。
最重要的部分是,雖然smaps
每次都以獨立的方式收集數據,但statm
使用在流程生命週期中增加或減少的計數器。有很多地方需要做簿記,也許有些地方不會像他們應該那樣升級櫃檯。這就是爲什麼IMO statm
低於smaps
,即使它需要更少的CPU週期來完成。
請注意,這是我根據常識得出的結論,但我可能是錯的 - 或許在計數器遞減和遞增時沒有內部不一致,相反,它們可能與smaps
不同。在這一點上,我認爲把它交給一些有經驗的內核維護者是明智的。
沒有人有任何有用的答案嗎? – tumbler