linux Memory 快照

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

转自:http://blog.chinaunix.net/uid-20769366-id-1849119.html

几乎看什么内核漏洞分析之类的文章,第一眼都是被 cat /proc/{pid}/maps
产生的一堆奇怪的信息唬住了,都不敢往下看
居然没有搜到关于它们的详细介绍,旁边也没有表头什么的解释信息
那就我来整理一下吧,方便后人。
 
ls /proc 能看到一些数字命名的文件夹,这个就不多说了,什么pid、fd的知识还是容易弄到的
拿init开刀,

[root@localhost proc]# cat /proc/1/statm
487 185 133 31 0 67 0
很简单地返回7组数字,每一个的单位都是一页 (常见的是4KB)
分别是
size:任务虚拟地址空间大小
Resident:正在使用的物理内存大小
Shared:共享页数
Trs:程序所拥有的可执行虚拟内存大小
Lrs:被映像倒任务的虚拟内存空间的库的大小
Drs:程序数据段和用户态的栈的大小
dt:脏页数量
接下来看看maps
[root@localhost proc]# cat /proc/1/maps
00110000-00111000 r-xp 00110000 00:00 0          [vdso]
0032b000-00347000 r-xp 00000000 fd:00 852733     /lib/ld-2.8.so
00347000-00348000 r--p 0001c000 fd:00 852733     /lib/ld-2.8.so
00348000-00349000 rw-p 0001d000 fd:00 852733     /lib/ld-2.8.so
0034b000-004ae000 r-xp 00000000 fd:00 852734     /lib/libc-2.8.so
004ae000-004b0000 r--p 00163000 fd:00 852734     /lib/libc-2.8.so
004b0000-004b1000 rw-p 00165000 fd:00 852734     /lib/libc-2.8.so
004b1000-004b4000 rw-p 004b1000 00:00 0
08048000-08067000 r-xp 00000000 fd:00 843075     /sbin/init
08067000-08068000 rw-p 0001e000 fd:00 843075     /sbin/init
08b42000-08b6a000 rw-p 08b42000 00:00 0          [heap]
b8046000-b8048000 rw-p b8046000 00:00 0
bfb4e000-bfb63000 rw-p bffeb000 00:00 0          [stack]

第一列代表内存段的虚拟地址
第二列代表执行权限,r,w,x不必说,p=私有 s=共享。不用说,heap和stack段不应该有x,否则就容易被xx,不过这个跟具体的版本有关
第三列代表在进程地址里的偏移量
第四列映射文件的主设备号和次设备号,通过 cat /proc/devices,得知fd是253 device-mapper
第五列映像文件的节点号,即inode
第六列是映像文件的路径
以前我很奇怪怎么会有两个相同的文件路径,原来
08048000-08067000 r-xp 00000000 fd:00 843075     /sbin/init
08067000-08068000 rw-p 0001e000 fd:00 843075     /sbin/init
一个是只读的,是代码段,一个是读写的,是数据段
至于为什么共享库分成了三个
0034b000-004ae000 r-xp 00000000 fd:00 852734     /lib/libc-2.8.so
004ae000-004b0000 r--p 00163000 fd:00 852734     /lib/libc-2.8.so
004b0000-004b1000 rw-p 00165000 fd:00 852734     /lib/libc-2.8.so
其中的004ae000-004b0000 r--p 00163000 fd:00 852734     /lib/libc-2.8.so
还是不能理解

 

单个进程的内存查看  cat /proc/[pid] 下面有几个文件: maps , smaps, status

 

maps 文件可以查看某个进程的代码段、栈区、堆区、动态库、内核区对应的虚拟地址,如果你还不了解linux进程的内存空间,可以参考这里

下图是maps文件内存示例

复制代码

Develop>cat /proc/self/maps 
00400000-0040b000 r-xp 00000000 fd:00 48              /mnt/cf/orig/root/bin/cat
0060a000-0060b000 r--p 0000a000 fd:00 48              /mnt/cf/orig/root/bin/cat
0060b000-0060c000 rw-p 0000b000 fd:00 48              /mnt/cf/orig/root/bin/cat 代码段
0060c000-0062d000 rw-p 00000000 00:00 0               [heap] 堆区
7f1fff43b000-7f1fff5d4000 r-xp 00000000 fd:00 861   /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff5d4000-7f1fff7d3000 ---p 00199000 fd:00 861  /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff7d3000-7f1fff7d7000 r--p 00198000 fd:00 861   /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff7d7000-7f1fff7d9000 rw-p 0019c000 fd:00 861   /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff7d9000-7f1fff7dd000 rw-p 00000000 00:00 0 
7f1fff7dd000-7f1fff7fe000 r-xp 00000000 fd:00 2554  /mnt/cf/orig/root/lib64/ld-2.15.so
7f1fff9f9000-7f1fff9fd000 rw-p 00000000 00:00 0 
7f1fff9fd000-7f1fff9fe000 r--p 00020000 fd:00 2554  /mnt/cf/orig/root/lib64/ld-2.15.so
7f1fff9fe000-7f1fff9ff000 rw-p 00021000 fd:00 2554  /mnt/cf/orig/root/lib64/ld-2.15.so
7f1fff9ff000-7f1fffa00000 rw-p 00000000 00:00 0 
7fff443de000-7fff443ff000 rw-p 00000000 00:00 0     [stack] 用户态栈区
7fff443ff000-7fff44400000 r-xp 00000000 00:00 0     [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0  [vsyscall] 内核区

复制代码

有时候可以通过不断查看某个进程的maps文件,通过查看其虚拟内存(堆区)是否不停增长来简单判断进程是否发生了内存溢出。

maps文件只能显示简单的分区,smap文件可以显示每个分区的更详细的内存占用数据

下图是smaps文件内存示例, 实际显示内容会将每一个区都显示出来,下面我只拷贝了代码段和堆区,

每一个区显示的内容项目是一样的,smaps文件各项含义可以参考这里

复制代码

Develop>cat /proc/self/smaps 
00400000-0040b000 r-xp 00000000 fd:00 48  /mnt/cf/orig/root/bin/cat
Size:                 44 kB 虚拟内存大小
Rss:                  28 kB 实际使用物理内存大小
Pss:                  28 kB
Shared_Clean:         0 kB 页面被改,则是dirty,否则是clean,页面引用计数>1,是shared,否则是private
Shared_Dirty:          0 kB
Private_Clean:        28 kB
Private_Dirty:         0 kB
Referenced:           28 kB
Anonymous:             0 kB
AnonHugePages:         0 kB
Swap:                  0 kB  处于交换区的页面大小
KernelPageSize:        4 kB  操作系统一个页面大小
MMUPageSize:           4 kB  体系结构MMU一个页面大小 
Locked:                0 kB

0060c000-0062d000 rw-p 00000000 00:00 0 [heap]
Size: 132 kB
Rss: 8 kB
Pss: 8 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 8 kB
Referenced: 8 kB
Anonymous: 8 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB

复制代码

 

下图是status文件内存示例, 加粗部分是内存相关的统计,

 

复制代码

Develop>cat /proc/24475/status
Name:    netio   可执行程序的名字
State:    R (running) 任务状态,运行/睡眠/僵死
Tgid:    24475  线程组号
Pid:    24475   进程id
PPid:    19635  父进程id
TracerPid:    0  
Uid:    0    0    0    0
Gid:    0    0    0    0
FDSize:    256 该进程最大文件描述符个数
Groups:    0 
VmPeak:     6330708 kB  内存使用峰值

VmSize:      268876 kB 进程虚拟地址空间大小

VmLck:           0 kB 进程锁住的物理内存大小,锁住的物理内存无法交换到硬盘

VmHWM:       16656 kB

VmRSS:       11420 kB 进程正在使用的物理内存大小

VmData:      230844 kB 进程数据段大小

VmStk:         136 kB 进程用户态栈大小

VmExe:         760 kB 进程代码段大小

VmLib:        7772 kB 进程使用的库映射到虚拟内存空间的大小

VmPTE:         120 kB 进程页表大小
VmSwap:           0 kB
Threads:    5
SigQ:    0/63346
SigPnd:    0000000000000000
ShdPnd:    0000000000000000
SigBlk:    0000000000000000
SigIgn:    0000000001000000
SigCgt:    0000000180000000
CapInh:    0000000000000000
CapPrm:    ffffffffffffffff
CapEff:    ffffffffffffffff
CapBnd:    ffffffffffffffff
Cpus_allowed:    01
Cpus_allowed_list:    0
Mems_allowed:    01
Mems_allowed_list:    0
voluntary_ctxt_switches:    201
nonvoluntary_ctxt_switches:    909

复制代码

可以看到,linux下内存占用是一个比较复杂的概念,不能

简单通过一个单一指标就判断某个程序“内存消耗”大小,原因有下面2点:

  • 进程所申请的内存不一定真正会被用到(malloc或mmap的实现)
  • 真正用到了的内存也不一定是只有该进程自己在用 (比如动态共享库)

关于内存的使用分析及本文几个命令的说明也可以参考这里

下面是查看整机内存使用情况的文件 /proc/meminfo

复制代码

Develop>cat /proc/meminfo 
MemTotal:        8112280 kB 所有可用RAM大小 (即物理内存减去一些预留位和内核的二进制代码大小)
MemFree:         4188636 kB LowFree与HighFree的总和,被系统留着未使用的内存
Buffers:           34728 kB 用来给文件做缓冲大小
Cached:           289740 kB 被高速缓冲存储器(cache memory)用的内存的大小
                           (等于 diskcache minus SwapCache )
SwapCached:            0 kB 被高速缓冲存储器(cache memory)用的交换空间的大小 
                            已经被交换出来的内存,但仍然被存放在swapfile中。
                            用来在需要的时候很快的被替换而不需要再次打开I/O端口
Active:           435240 kB 在活跃使用中的缓冲或高速缓冲存储器页面文件的大小,
                              除非非常必要否则不会被移作他用
Inactive:         231512 kB 在不经常使用中的缓冲或高速缓冲存储器页面文件的大小,可能被用于其他途径.
Active(anon):     361252 kB 
Inactive(anon):   120688 kB
Active(file):      73988 kB
Inactive(file):   110824 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB 交换空间的总大小
SwapFree:              0 kB 未被使用交换空间的大小
Dirty:                 0 kB 等待被写回到磁盘的内存大小
Writeback:             0 kB 正在被写回到磁盘的内存大小
AnonPages:        348408 kB 未映射页的内存大小
Mapped:            33600 kB 已经被设备和文件等映射的大小
Shmem:            133536 kB 
Slab:              55984 kB 内核数据结构缓存的大小,可以减少申请和释放内存带来的消耗
SReclaimable:      25028 kB 可收回Slab的大小
SUnreclaim:        30956 kB 不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)
KernelStack:        1896 kB 内核栈区大小
PageTables:         8156 kB 管理内存分页页面的索引表的大小
NFS_Unstable:          0 kB 不稳定页表的大小
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2483276 kB
Committed_AS:    1804104 kB
VmallocTotal:   34359738367 kB 可以vmalloc虚拟内存大小
VmallocUsed:      565680 kB 已经被使用的虚拟内存大小
VmallocChunk:   34359162876 kB
HardwareCorrupted:     0 kB
HugePages_Total:    1536  大页面数目
HugePages_Free:        0 空闲大页面数目
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB 大页面一页大小
DirectMap4k:       10240 kB 
DirectMap2M:     8302592 kB

复制代码

 

手动解析HPROF 文件的过程。

maps
23258 b5758000-b5e3d000 r-xp 00000000 fd:00 223303                             /data/data/com.xxx.phone/files/storage/com.xxx.maindex/version.1/lib/libxxx.so   //代码段
23259 b5e3d000-b5e3e000 ---p 00000000 00:00 0 
23260 b5e3e000-b5e7a000 r--p 006e5000 fd:00 223303                             /data/data/com.xxx.phone/files/storage/com.xxx.maindex/version.1/lib/libxxx.so                            
23261 b5e7a000-b5e86000 rw-p 00721000 fd:00 223303                       //数据段 && userstack      /data/data/com.xxx.phone/files/storage/com.xxx.maindex/version.1/lib/libxxx.so

b5758000-b5e3d000 r-xp 00000000 fd:00 223303//地址范围b5758000-b5e3d000 权限读,写-可执行,私有 (代码段)
进程内偏移量00000000 主设备号fd (253 device-mapper)次设备号00, inode 223303

hprof 中一个内存分配的item:
z 1  sz  1382400  num    1  bt f3a9da84 f5ad0d00 b58edda4 b58b90d4 b58baf40 b58bc9a0 b58bd120 b57f9ebc b57fa490 b57a23f8 f6f17702 f6ef1040 

//address2line
 b58edda4−b5758000 = 195DA4

 $NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addne -e out/target/product/generic/symbols/system/lib/libxxx-3.5.2.2.so 195DA4
/home/lyl/source/frameworks/main/osal/src/opengl/hal_video_opengl.cpp:184

 

23264 b6069000-b606a000 ---p 00000000 00:00 0
23265 b606a000-b606b000 ---p 00000000 00:00 0
23266 b606b000-b616e000 rw-p 00000000 00:00 0                                  [stack:23688]
23267 b616e000-b616f000 ---p 00000000 00:00 0
23268 b616f000-b6170000 ---p 00000000 00:00 0
23269 b6170000-b6273000 rw-p 00000000 00:00 0                                  [stack:23687]


可以看出每个栈帧空间之前8K 保护区。//TODO

 

转载于:https://my.oschina.net/u/269082/blog/1486490

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Memory Analyzer是一种基于Java的工具,用于分析和诊断Java应用程序中的内存问题。它允许开发人员深入了解应用程序的内存使用情况,识别内存泄漏和其他内存问题,并为优化内存使用提供指导。 Memory Analyzer是在JDK8环境下开发的,它支持Java堆转储文件(.heap、.hprof和.phd格式)和系统转储文件,而且不会影响应用程序的性能。除了基本的垃圾收集器信息之外,Memory Analyzer还提供了大量用于解释存储在内存中的对象的功能,包括查找重复对象、查找大型对象、跟踪垃圾收集根等。 在使用Memory Analyzer时,需要下载并安装著名的Eclipse平台,然后从Eclipse MarketPlace安装Memory Analyzer插件,然后就可以通过Eclipse右键单击Java堆转储文件或系统转储文件来打开Memory Analyzer。之后,用户可以使用Memory Analyzer的内存浏览器、直方图、条形图、表格和其它工具来查看应用程序中的对象、堆使用情况、类实例数等。 总而言之,Memory Analyzer是一种非常有用的工具,它可以帮助开发人员快速发现Java应用程序中的内存问题,优化内存使用情况,为Java应用程序的稳定性和性能提供支持。 ### 回答2: Memory Analyzer是Java内存分析工具的一种,可以用来检测内存泄漏问题和内存使用情况。而JDK8是Java开发工具包的一种,是Java的主要版本之一,包含了许多最新的特性和改进。 Memory Analyzer在JDK8中得到了更好的支持和完善,具有更为强大的能力和更广泛的适用性。JDK8增加了进一步丰富和完善的API,通过一系列优化和改进,使得内存分析工作更加精确和高效。 在使用Memory Analyzer进行内存分析时,通常需要先收集内存快照。JDK8中的增量CMS和G1收集器可以帮助我们更好地获得内存快照,并且提供更好的性能和稳定性。 除了增强的API和更好的收集器支持,JDK8还提供了更高级的内存分析工具和技术,例如Java Flight Recorder和Java Mission Control。这些工具可以帮助我们更深入地了解内存使用情况,识别潜在的性能瓶颈,以及对代码进行调优和优化。 综合来说,Memory Analyzer在JDK8中得到了更为全面和完善的支持和升级,可以帮助我们更好地进行内存分析和优化。同时,JDK8也提供了更多高级工具和技术,为内存分析工作提供了更多选择和灵活性。 ### 回答3: Memory Analyzer是一个Java Heap Analyzer的工具,它可以用来分析Java虚拟机的堆内存,并查找潜在的内存泄漏、内存溢出等问题。最新版本的Memory Analyzer是支持JDK8的,与之前版本相比,它提供了更好的性能和更多的功能。它使用Java6平台作为基础,支持在Windows、Linux和Mac OS X等操作系统上运行。 Memory Analyzer的主要特点是它可以直接读取Java堆转储文件,不需要重新启动Java应用程序,从而避免了影响应用程序性能的问题。该工具使用Eclipse作为前端,可以方便地查看Java堆快照中的对象。可以根据各种条件过滤对象以便进行更深入的分析。所有的分析结果都以可视化形式呈现,便于用户理解。 Memory Analyzer可以在堆内存中查找所有类型的问题,包括内存泄漏、内存溢出、死锁、线程安全等问题。它可以展示Java应用程序的内存使用情况,帮助用户在项目执行过程中及时检测和处理问题。对于大型Java应用程序,Memory Analyzer是一个非常有用的工具,可以帮助快速诊断内存问题,提高系统的可靠性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值