首页 > 其他分享 >/proc/pids/smaps

/proc/pids/smaps

时间:2023-11-09 16:01:43浏览次数:39  
标签:kB smaps 映射 pte 内存 pids proc 虚拟内存 页面

Linux内存管理 -- /proc/{pid}/smaps讲解

基本介绍

/proc/PID/smaps 文件是基于 /proc/PID/maps 的扩展,他展示了一个进程的内存消耗,比同一目录下的maps文件更为详细。

值得说明一下的是,每一个VMA(虚拟内存区域,即一个 vm_area_struct 结构指向的内存区域)都有如下的一系列数据:

08048000-080bc000 r-xp 00000000 03:02 13130      /bin/bash
 
Size:               1084 kB
Rss:                 892 kB
Pss:                 374 kB
Shared_Clean:        892 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:          892 kB
Anonymous:             0 kB
ShmemPmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB
THPeligible:           0
VmFlags: rd ex mr mw me dw

第一行基础信息

在讲解字段含义之前,我们必须知道什么匿名映射:

在Linux 内存管理的进程用户态内存分布中提到过,映射分为文件映射和匿名映射。

文件映射就是磁盘中的数据通过文件系统映射到内存再通过文件映射映射到虚拟空间,这样,用户就可以在用户空间通过 open ,read, write 等函数区操作文件内容。至于实际的代码,open,read,write,close,mmap... 操作的虚拟地址都属于文件映射。

匿名映射就是用户空间需要分配一定的物理内存来存储数据,这部分内存不属于任何文件,内核就使用匿名映射将内存中的某段物理地址与用户空间一一映射,这样用户就可用直接操作虚拟地址来范围这段物理内存。比如使用malloc申请内存。

  • 08048000-080bc000 是该虚拟内存段的开始和结束位置
  • r-xp 内存段的权限,分别是可读、可写、可运行、私有或共享,最后一位p代表私有,s代表共享
  • 00000000 该虚拟内存段起始地址在对应的映射文件中以页为单位的偏移量,对匿名映射,它等于0或者vm_start/PAGE_SIZE
  • 03:02 文件的主设备号和次设备号。对匿名映射来说,因为没有文件在磁盘上,所以没有设备号,始终为00:00。对有名映射来说,是映射的文件所在设备的设备号。
  • 13130 被映射到虚拟内存的文件的索引节点号,通过该节点可以找到对应的文件,对匿名映射来说,因为没有文件在磁盘上,所以没有节点号,始终为00:00。
  • /bin/bash 被映射到虚拟内存的文件名称。后面带(deleted)的是内存数据,可以被销毁。对有名来说,是映射的文件名。对匿名映射来说,是此段虚拟内存在进程中的角色。[stack]表示在进程中作为栈使用,[heap]表示堆。其余情况则无显示。

第一行的信息完全同于在maps文件中输出的信息。对于不熟悉maps文件的读者可以先了解maps的字段的含义与实现机制。

详细信息

Size:虚拟内存空间大小。但是这个内存值不一定是物理内存实际分配的大小,因为在用户态上,虚拟内存总是延迟分配的。这个值计算也非常简单,就是该VMA的开始位置减结束位置。

延迟分配就是当进程申请内存的时候,Linux会给他先分配页,但是并不会区建立页与页框的映射关系,意思就是说并不会分配物理内存,而当真正使用的时候,就会产生一个缺页异常,硬件跳转page fault处理程序执行,在其中分配物理内存,然后修改页表(创建页表项)。异常处理完毕,返回程序用户态,继续执行。

Rss:是实际分配的内存,这部分物理内存已经分配,不需要缺页中断就可以使用的。

这里有一个公式计算Rss:
Rss=Shared_Clean+Shared_Dirty+Private_Clean+Private_Dirty
  • share/private:该页面是共享还是私有。
  • dirty/clean:该页面是否被修改过,如果修改过(dirty),在页面被淘汰的时候,就会把该脏页面回写到交换分区(换出,swap out)。有一个标志位用于表示页面是否dirty。
  • share/private_dirty/clean 计算逻辑:
    查看该page的引用数,如果引用>1,则归为shared,如果是1,则归为private,同时也查看该page的flag,是否标记为_PAGE_DIRTY,如果不是,则认为干净的。

Pss(proportional set size):是平摊计算后的实际物理使用内存(有些内存会和其他进程共享,例如mmap进来的)。实际上包含下面private_clean+private_dirty,和按比例均分的shared_clean、shared_dirty。

举个计算Pss的例子:
如果进程A有x个private_clean页面,有y个private_dirty页面,有z个shared_clean仅和进程B共享,有h个shared_dirty页面和进程B、C共享。那么进程A的Pss为:

x + y + z/2 + h/3

Referenced:当前页面被标记为已引用或者包含匿名映射(The amount of memory currently marked as referenced or a mapping associated with a file may contain anonymous pages)。

Anonymous:匿名映射的物理内存,这部分内存不来自于文件的内存大小。

ShmemPmdMapped:PMD页面已经被映射的共享(shmem / tmpfs)内存量。在官方文档中,这样解释:"ShmemPmdMapped" shows the ammount of shared (shmem/tmpfs) memory backed by huge pages.

Shared/Private_Hugetlb:由hugetlbfs页面支持的内存使用量,由于历史原因,该页面未计入“ RSS”或“ PSS”字段中。 并且这些没有包含在Shared/Private_Clean/Dirty 字段中。

Swap:存在于交换分区的数据大小(如果物理内存有限,可能存在一部分在主存一部分在交换分区)

SwapPss:这个我并没有找到对应解释,但从源码可以得知,计算逻辑就跟pss一样,只不过针对的是交换分区的内存。

static void smaps_pte_entry(pte_t *pte, unsigned long addr,
        struct mm_walk *walk)
{
    struct mem_size_stats *mss = walk->private;
    struct vm_area_struct *vma = walk->vma;
    struct page *page = NULL;

    if (pte_present(*pte)) {//----------------------------------页面在内存中
        page = vm_normal_page(vma, addr, *pte);
    } else if (is_swap_pte(*pte)) {//---------------------------页面被swap出
        swp_entry_t swpent = pte_to_swp_entry(*pte);

        if (!non_swap_entry(swpent)) {
            int mapcount;

            mss->swap += PAGE_SIZE;
            mapcount = swp_swapcount(swpent);
            if (mapcount >= 2) {
                u64 pss_delta = (u64)PAGE_SIZE << PSS_SHIFT;
               do_div(pss_delta, mapcount);
                mss->swap_pss += pss_delta; // --------- 如果引用超过1,就将均值加入swap_pss中
            } else {
                mss->swap_pss += (u64)PAGE_SIZE << PSS_SHIFT;// ------------ 直接加一个页大小
            }
       } else if (is_migration_entry(swpent))
            page = migration_entry_to_page(swpent);
    }

    if (!page)//----------------------------------------------如果页面不存在,就不用更新mss其他信息了;如果存在,调用smaps_account()更新mss。
        return;
smaps_account(mss, page, PAGE_SIZE, pte_young(*pte), pte_dirty(*pte));
}

KernelPageSize:内核一页的大小
MMUPageSize:MMU页大小,大多数情况下,和KernelPageSize大小一样。

Locked:常驻物理内存的大小,这些页不会被换出。

THPeligible:映射是否符合分配THP的条件。如果为true,则为1,否则为0。 它仅显示当前状态。

THP,透明大页(Transparent Huge Pages),RHEL 6 开始引入,目的是使用更大的内存页面(memory page size) 以适应越来越大的系统内存,让操作系统可以支持现代硬件架构的大页面容量功能。与标准大页的区别在于分配机制,标准大页管理是预分配的方式,而透明大页管理则是动态分配的方式。

VmFlags:表示与特定虚拟内存区域关联的内核标志。标志如下:

rd  - readable
wr  - writeable
ex  - executable
sh  - shared
mr  - may read
mw  - may write
me  - may execute
ms  - may share
gd  - stack segment growns down
pf  - pure PFN range
dw  - disabled write to the mapped file
lo  - pages are locked in memory
io  - memory mapped I/O area
sr  - sequential read advise provided
rr  - random read advise provided
dc  - do not copy area on fork
de  - do not expand area on remapping
ac  - area is accountable
nr  - swap space is not reserved for the area
ht  - area uses huge tlb pages
ar  - architecture specific flag
dd  - do not include area into core dump
sd  - soft-dirty flag
mm  - mixed map area
hg  - huge page advise flag
nh  - no-huge page advise flag
mg  - mergable advise flag

标签:kB,smaps,映射,pte,内存,pids,proc,虚拟内存,页面
From: https://www.cnblogs.com/linhaostudy/p/17821883.html

相关文章

  • /proc/buddyinfo
    在应用程序设计过程中,内存是很重要的资源,而计算机主机的内存资源时有限的。一般而言我们可以申请到的内存是有限的,并不是想申请多大就有多大就可以申请多大的。/proc/buddyinfo文件里,就记录着系统的内存资源。linux内核中使用了buddy算法来管理内存以减少内存碎片的产生,buddy算法......
  • Temporal Point Processes
    目录TPPEvolutionarypointprocessesConditionalintensityfunction[\(t\)]Conditionalintensityfunction[\(t,\kappa\)]InferenceSimulationInverseMethodOgata’smodifiedthinningalgorithm例子RasmussenJ.G.Lecturenotes:Temporalpointprocessesandt......
  • Unity 自定义Postprocess Kawase Blur
    前言本篇将介绍如何通过添加RenderFeature实现自定义的postprocess——KawaseBlur关于RenderFeature的基础可以看这篇https://www.cnblogs.com/chenglixue/p/17816447.htmlKawaseBlur介绍因为毛神对于十大模糊算法的介绍已经整理得十分详细了,所以这里不会深入,但会大致讲讲它......
  • Unity 自定义Postprocess BSC明度饱和度对比度
    前言本篇将介绍如何通过添加RenderFeature实现自定义的postprocess——调整屏幕的明度、饱和度、对比度(以下统称BSC)关于RenderFeature的基础可以看这篇https://www.cnblogs.com/chenglixue/p/17816447.htmlShaderBrightness:很简单乘以rendertargettexture即可Saturatio......
  • Git拉取失败 Your local changes would be overwritten by merge.Commit, stash or re
    今天在使用Gitpull代码的时候,出现了这样的问题:GitPullFailedYourlocalchangeswouldbeoverwrittenbymerge.Commit,stashorrevertthemtoproceed.这是因为本地有文件改动未提交,并且该文件和Git服务器最新版本有冲突,此时pull更新就会提示错误,无法更新。Git小......
  • Windows ObjectType Hook 之 SecurityProcedure
    1、背景  ObjectTypeHook是基于ObjectType的一种深入的Hook,比起常用的SSDTHook更为深入。  有关ObjectType的分析见文章《Windows驱动开发学习记录-ObjectTypeHook之ObjectType结构相关分析》。  这里进行的Hook为其中之一的SecurityProcedure。文章实......
  • Process-与操作系统中的进程进行交互
    Process介绍在Java中,Process类是一个抽象类,它提供了与操作系统中的进程进行交互的方法。当你在Java程序中启动一个新的进程(例如,运行一个外部程序或脚本)时,JVM会创建一个Process实例来代表这个新的进程。Process类提供了以下主要的方法:getInputStream():获取进程的标准输出流。你......
  • subprocess
    目录1.简介2.subprocess.run2.1应用场景2.2常用参数2.3示例3.subprocess.Popen3.1应用场景3.2常用参数3.3方法3.4示例1.简介subprocess是Python标准库中的模块,用于在Python程序中启动新的外部进程并与它们进行交互。这个模块提供了多种方法来执行外部命令,捕获命令的......
  • Windows ObjectType Hook 之 OkayToCloseProcedure
    1、背景  ObjectTypeHook是基于ObjectType的一种深入的Hook,比起常用的SSDTHook更为深入。  有关ObjectType的分析见文章《Windows驱动开发学习记录-ObjectTypeHook之ObjectType结构相关分析》。  这里进行的Hook为其中之一的OkayToCloseProcedure。文......
  • 汇编-ExitProcess结束程序
    INVOKEExitProcess,0参数:退出代码  ......