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

/proc/pids/smaps的更多相关文章

  1. Python classes to extract information from the Linux kernel /proc files.

    python/python-linux-procfs/python-linux-procfs.git - Python classes to extract information from the ...

  2. ndk学习13: proc

    一.进程相关信息 /proc目录中包含许多以数字命名的子目录,这些数字表示系统当前正在运行进程的进程号,里面包含对应进程相关的多个信息文件 结构如下: 进程相关的信息如下: 部分信息如下 cmdlin ...

  3. ps&&/proc/pid/xxx

    ps 如果想看一个进程的启动时间,可以用lstart来看 [root@jiangyi02.sqa.zmf /home/ahao.mah] #ps -eo pid,lstart,etime,cmd |g ...

  4. stuff in /proc/PID/

    Table of Contents 1. /proc/PID/cwd 2. /proc/PID/clear_refs 3. /proc/PID/coredump_filter 4. /proc/PID ...

  5. /PROC/MEMINFO之谜

    网站转自:http://linuxperf.com/?p=142 非常技术的网站,够看上一阵子的(一篇文章) /proc/meminfo是了解Linux系统内存使用状况的主要接口,我们最常用的”fre ...

  6. Linux中的Buffer Cache和Page Cache echo 3 > /proc/sys/vm/drop_caches Slab内存管理机制 SLUB内存管理机制

    Linux中的Buffer Cache和Page Cache echo 3 > /proc/sys/vm/drop_caches   Slab内存管理机制 SLUB内存管理机制 http://w ...

  7. linux程序分析工具介绍(一)—-”/proc”

    写在最前面:在开始本文之前,笔者认为先有必要介绍一下linux下的man,如果读者手头用linux系统,直接在终端输入man man便可以看到详细的说明,我在这里简单的总结一下,man命令是用来查看l ...

  8. linux 内存查看方法:meminfo\maps\smaps\status 文件解析

    linux 下面查看内存有多种渠道,比如通过命令 ps ,top,free 等,比如通过/proc系统,一般需要比较详细和精确地知道整机内存/某个进程内存的使用情况,最好通过/proc 系统,下面介绍 ...

  9. [笔记] dumpsys meminfo数据与smaps文件对应关系

    通过cat /proc/$PID/smaps可以查看进程内存的详细映射情况.详细解析可以参考kernel的文档/Documentation/filesystems/proc.txt 如果我们的Andr ...

  10. SHELL:Find Memory Usage In Linux (统计每个程序内存使用情况)

    转载一个shell统计linux系统中每个程序的内存使用情况,因为内存结构非常复杂,不一定100%精确,此shell可以在Ghub上下载. [root@db231 ~]# ./memstat.sh P ...

随机推荐

  1. SQL实战从在职到离职(1) 如何处理连续查询

    书接上回,最近离职在家了实在无聊,除了看看考研的书,打打dnf手游,也就只能写写代码,结果昨晚挂在某平台的一个技术出售有人下单了,大概业务是需要帮忙辅导一些面试需要用到的SQL. 回想了下,在该平台接 ...

  2. 对比python学julia(第三章:游戏编程)--(第四节)捕鱼达人(5)

    4.3.    编程实现 (续上) 3. 实现射击捕鱼 在第 3 个阶段,将按照"编程思路"中介绍的射击捕鱼的算法进行编程,实现让玩家操控大炮射击捕鱼.在"bydr&qu ...

  3. 【SQL】 牛客网SQL训练Part3 较难难度

    获取当前薪水第二多的员工的emp_no以及其对应的薪水salary 请你查找薪水排名第二多的员工编号emp_no.薪水salary.last_name以及first_name,不能使用order by ...

  4. 【MySQL】拆分经纬度字段

    数据结构: 表中一字段存储经度和纬度: +---------------------------+ | INSTALL_LOLA_NUM | +---------------------------+ ...

  5. 【Java】Collection子接口:其二 Set 组接口

    Collection子接口:其二 Set 组接口 - Set接口是Collection的子接口,Set没有提供额外的方法 - Set集合中不允许包含重复的元素,如果重复添加,只保留最新添加的那一个 - ...

  6. 【转载】 linux中umask命令介绍

    版权声明:本文为CSDN博主「立二拆四i」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/weixin_4408 ...

  7. spring5的新特性

    1.背景 2.依赖环境的变化 整个 Spring5 框架的代码基于 Java8,运行时兼容 JDK9,许多不建议使用的类和方 法在代码库中删除 3.自带了通用的日志封装 3.1.日志的简单使用 Spr ...

  8. 【selenium + python】之BSTestRunner生成测试报告时报错:NameError: name 'unicode' is not defined

    好久没生成报告了,最近使用的时候报了一个错误!用的这个报告模板BSTestRunner但是汇报下面的错误: NameError: name 'unicode' is not defined 经查询得知 ...

  9. 将workbench 导出的sql数据修改为 oracle 的sql版本

    将导出的文件内容复制到 dd1.txt,或其它文件,修改path的值即可 修改后的sql文件为 dd1.sql : 替换的内容: 1. 全局替换了一些字符串,如` 2. workbench导出的sql ...

  10. CM3和ARM7的差异

    此文章由文心一言生成,引用请标注作者:文心一言CM3通常指的是Cortex-M3,它是ARM公司设计的一种基于ARMv7-M架构的32位处理器内核,主要用于嵌入式系统.而ARM7则是ARM公司早期设计 ...