linux Memory 快照

Linux 下面查看內存有多種渠道,好比經過命令 ps ,top,free 等,好比經過/proc系統,通常須要比較詳細和精確地知道整機內存/某個進程內存的使用狀況,最好經過/proc 系統,下面介紹/proc系統下內存相關的幾個文件html

轉自:http://blog.chinaunix.net/uid-20769366-id-1849119.htmlnode

幾乎看什麼內核漏洞分析之類的文章,第一眼都是被 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, statuslinux

 

maps 文件能夠查看某個進程的代碼段、棧區、堆區、動態庫、內核區對應的虛擬地址,若是你還不瞭解linux進程的內存空間,能夠參考這裏android

下圖是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文件能夠顯示每一個分區的更詳細的內存佔用數據app

下圖是smaps文件內存示例, 實際顯示內容會將每個區都顯示出來,下面我只拷貝了代碼段和堆區,ide

每個區顯示的內容項目是同樣的,smaps文件各項含義能夠參考這裏ui

複製代碼

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 kBidea

複製代碼

 

下圖是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
相關文章
相關標籤/搜索