Linux作业系统:/proc/[pid]/smaps与/proc/[pid]/statm [英] Linux OS: /proc/[pid]/smaps vs /proc/[pid]/statm

查看:122
本文介绍了Linux作业系统:/proc/[pid]/smaps与/proc/[pid]/statm的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想计算单个进程的内存使用情况.因此,经过一番研究,我发现了smap和statm.

I would like calculate the memory usage for single process. So after a little bit of research I came across over smaps and statm.

首先,什么是smap和statm?有什么区别?

First of all what is smaps and statm? What is the difference?

statm有一个RSS字段,在smap中,我总结了所有RSS值.但是对于同一过程,这些值是不同的.我知道statm的度量单位是页面.为了进行比较,我将该值转换为smap中的kb.但是这些值并不相等.即使这两个值代表同一过程的rss值,为什么这两个值也不同?

statm has a field RSS and in smaps I sum up all RSS values. But those values are different for the same process. I know that statm measures in pages. For comparison purposes I converted that value in kb as in smaps. But those values are not equal. Why do these two values differ, even though they represent the rss value for the same process?

statm
232214 80703 7168 27 0 161967 0 (measured in pages, pages size is 4096)

smaps
Rss 1956

我的目的是计算单个进程的内存使用量.我对两个值感兴趣.USS和PSS.我可以仅使用smap获得这两个值吗?这个值正确吗?另外,我想以百分比形式返回该值.

My aim is to calculate the memory usage for a single process. I am interested in two values. USS and PSS. Can I gain those two values by just using smaps? Is that value correct? Also, I would like to return that value as percentage.

推荐答案

我认为 statm smaps 的近似简化,但价格昂贵.在查看了源代码之后,我得出了这个结论:

I think statm is an approximated simplification of smaps, which is more expensive to get. I came to this conclusion after I looked at the source:

您在 smaps 中看到的信息在 /fs/proc/task_mmu.c :

The information you see in smaps is defined in /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,

mss 中的信息由

The information in mss is used by walk_page_vma defined in /mm/pagewalk.c. However, the mss member resident is not filled in walk_page_vma - instead, walk_page_vma calls callback specified in smaps_walk:

.pmd_entry = smaps_pte_range,
.private = &mss,

像这样:

  if (walk->pmd_entry)
      err = walk->pmd_entry(pmd, addr, next, walk);

那么我们在

So what does our callback, smaps_pte_range in /fs/proc/task_mmu.c, do? It calls smaps_pte_entry and smaps_pmd_entry in some circumstances, out of which both call statm_account(), which in turn... upgrades resident size! All of these functions are defined in the already linked task_mmu.c so I didn't post relevant code snippets as they can be easily seen in the linked sources.

PTE代表页面表条目,PMD代表页面中间目录.因此,基本上,我们将遍历与给定进程关联的页面条目,并根据情况更新RAM的使用情况.

PTE stands for Page Table Entry and PMD is Page Middle Directory. So basically we iterate through the page entries associated with given process and update RAM usage depending on the circumstances.

您在 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 ).在此实施中,我们看到了

This time, resident is filled by task_statm. This one has two implementations, one in /fs/proc/task_mmu.c and second in /fs/proc/task_nomm.c. Since they're almost surely mutually exclusive, I'll focus on the implementation in task_mmu.c (which also contained task_smaps). In this implementation we see that

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 .所有的修改似乎都是由/mm/中的文件完成的,并且似乎有很多修改,因此我在这里没有包括它们.

it queries some counters, namely, MM_FILEPAGES and MM_ANONPAGES. These counters are modified during different operations on memory such as do_wp_page defined at /mm/memory.c. All of the modifications seem to be done by the files located in /mm/ and there seem to be quite a lot of them, so I didn't include them here.

smaps 对所有引用的内存区域进行复杂的迭代,并使用收集的信息更新 resident 的大小. statm 使用其他人已经计算出的数据.

smaps does complicated iteration through all referenced memory regions and updates resident size using the collected information. statm uses data that was already calculated by someone else.

最重要的部分是,虽然 smaps 每次都以独立的方式收集数据,但 statm 使用的计数器在过程生命周期中会递增或递减.有很多地方需要记账,也许有些地方没有像应有的那样升级柜台.这就是IMO statm 不如 smaps 的原因,即使完成所需的CPU周期更少.

The most important part is that while smaps collects the data each time in an independent manner, statm uses counters that get incremented or decremented during process life cycle. There are a lot of places that need to do the bookkeeping, and perhaps some places don't upgrade the counters like they should. That's why IMO statm is inferior to smaps, even if it takes fewer CPU cycles to complete.

请注意,这是我根据常识得出的结论,但我可能是错的-也许计数器的递减和递增没有内部矛盾,相反,它们对某些页面的计数可能与 smaps .在这一点上,我认为将它带给一些经验丰富的内核维护者是明智的.

Please note that this is the conclusion I drew based on common sense, but I might be wrong - perhaps there are no internal inconsistencies in counter decrementing and incrementing, and instead, they might count some pages differently than smaps. At this point I believe it'd be wise to take it to some experienced kernel maintainers.

这篇关于Linux作业系统:/proc/[pid]/smaps与/proc/[pid]/statm的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆