草庐IT

Linux 操作系统 :/proc/[pid]/smaps vs/proc/[pid]/statm

coder 2023-06-19 原文

我想计算单个进程的内存使用量。因此,经过一些研究后,我发现了 smaps 和 statm。

首先什么是smaps和statm?有什么区别?

statm 有一个 RSS 字段,在 smaps 中我总结了所有 RSS 值。但是对于同一个过程,这些值是不同的。我知道 statm 以页面为单位进行测量。出于比较目的,我将该值转换为 kb,就像在 smaps 中一样。但这些值并不相等。 为什么这两个值不同,即使它们代表同一进程的 rss 值?

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

smaps
Rss 1956

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

最佳答案

我认为 statmsmaps 的近似简化,获取它的成本更高。我看了源码后得出了这个结论:

map

您在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,

mss中的信息被/mm/pagewalk.c中定义的walk_page_vma使用.但是,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 in /fs/proc/task_mmu.c , 做? 它在某些情况下调用 smaps_pte_entrysmaps_pmd_entry,其中都调用 statm_account(),这反过来......升级 resident 尺寸!所有这些函数都在已链接的 task_mmu.c 中定义,因此我没有发布相关代码片段,因为它们可以在链接的源代码中轻松看到。

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

统计

您在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;
}

这一次,residenttask_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_FILEPAGESMM_ANONPAGES。这些计数器在对内存的不同操作期间被修改,例如在 /mm/memory.c 定义的 do_wp_page .所有的修改似乎都是由位于/mm/ 中的文件完成的,而且似乎有很多,所以我没有在这里包含它们。

结论

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

最重要的部分是 smaps 每次都以独立的方式收集数据,而 statm 使用在进程生命周期中递增或递减的计数器。需要做记账的地方很多,也许有些地方并没有按照应有的方式升级柜台。这就是为什么 IMO statm 不如 smaps,即使它需要更少的 CPU 周期来完成。

请注意,这是我根据常识得出的结论,但我可能是错的 - 也许在计数器递减和递增方面没有内部不一致,相反,它们可能以不同于 smaps。在这一点上,我认为将它交给一些有经验的内核维护者是明智的。

关于Linux 操作系统 :/proc/[pid]/smaps vs/proc/[pid]/statm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30744333/

有关Linux 操作系统 :/proc/[pid]/smaps vs/proc/[pid]/statm的更多相关文章

  1. 电脑0x0000001A蓝屏错误怎么U盘重装系统教学 - 2

      电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。  准备工作:  1、U盘一个(尽量使用8G以上的U盘)。  2、一台正常联网可使用的电脑。  3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。  4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。  U盘启动盘制作步骤:  注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注

  2. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  3. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  4. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  5. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  6. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  7. ruby - 在没有基准或时间的情况下用 Ruby 测量用户时间或系统时间 - 2

    因为我现在正在做一些时间测量,我想知道是否可以在不使用Benchmark类或命令行实用程序time的情况下测量用户时间或系统时间。使用Time类只显示挂钟时间,而不显示系统和用户时间,但是我正在寻找具有相同灵active的解决方案,例如time=TimeUtility.now#somecodeuser,system,real=TimeUtility.now-time原因是我有点不喜欢Benchmark,因为它不能只返回数字(编辑:我错了-它可以。请参阅下面的答案。)。当然,我可以解析输出,但感觉不对。*NIX系统的time实用程序也应该可以解决我的问题,但我想知道是否已经在Ruby中实

  8. ruby - 在 Ruby 中是否有一种惯用的方法来操作 2 个数组? - 2

    a=[3,4,7,8,3]b=[5,3,6,8,3]假设数组长度相同,是否有办法使用each或其他一些惯用方法从两个数组的每个元素中获取结果?不使用计数器?例如获取每个元素的乘积:[15,12,42,64,9](0..a.count-1).eachdo|i|太丑了...ruby1.9.3 最佳答案 使用Array.zip怎么样?:>>a=[3,4,7,8,3]=>[3,4,7,8,3]>>b=[5,3,6,8,3]=>[5,3,6,8,3]>>c=[]=>[]>>a.zip(b)do|i,j|c[[3,5],[4,3],[7,6],

  9. ruby-on-rails - 如何让 Rails View 返回其关联的操作名称? - 2

    我有一个非常简单的Controller来管理我的Rails应用程序中的静态页面:classPagesController我怎样才能让View模板返回它自己的名字,这样我就可以做这样的事情:#pricing.html.erb#-->"Pricing"感谢您的帮助。 最佳答案 4.3RoutingParametersTheparamshashwillalwayscontainthe:controllerand:actionkeys,butyoushouldusethemethodscontroller_nameandaction_nam

  10. ruby - 以毫秒为单位获取当前系统时间 - 2

    在Ruby中,以毫秒为单位获取自纪元(1970)以来的当前系统时间的正确方法是什么?我试过了Time.now.to_i,好像不是我想要的结果。我需要结果显示毫秒并且使用long类型,而不是float或double。 最佳答案 (Time.now.to_f*1000).to_iTime.now.to_f显示包含十进制数字的时间。要获得毫秒数,只需将时间乘以1000。 关于ruby-以毫秒为单位获取当前系统时间,我们在StackOverflow上找到一个类似的问题:

随机推荐