Linux程序資源佔用分析
0 引言
最近在分析安卓程式上的monkey測試日誌時發現,需要了解下Linux程序資源佔用情況及其檢視方法。之前在windows上有ProcessExplorer可以直接檢視,在Linux下就沒這麼方便了,只能通過命令列來檢視。
所以本文的目標就在於:在你知道你要分析的程序名之後,通過命令列工具讀取程序的PID、CPU佔用情況、記憶體佔用情況、已開啟檔案描述符、網路情況。
1 找到程序PID
目前使用比較經典的命令是top
。比如我想找player關鍵詞的程序,可以使用:
# top | grep player 2319 u0_a127 20 0 22% S 450 3254600K 1162720K ta com.real.simpleplayer 2134 u0_a14 20 0 0% S 13 1410516K 37624K bg com.huawei.hwvplayer.youku
這樣就可以很簡單找到你需要的程序PID。當然也可以使用其他命令列工具,比如atop、Htop等等。(參考文獻中有很多,有興趣可以檢視下)
2 給定程序資源佔用情況
這裡的資源包括:CPU、記憶體、開啟控制代碼、內部執行緒。(上面提到的工具都有對應的資料列,這裡僅提供最原始的查閱方式。)
linux的新建立程序會自動建立/proc/pid
目錄,其中包含以下部分:
目錄名 | 功能說明 |
---|---|
cmdline | 包含了用於啟動程序的命令列 |
cwd | 包含了當前程序工作目錄的連結 |
environ | 包含了可用程序環境變數的列表 |
exe | 包含了正在程序中執行的可執行檔案的連結 |
fd | 包含了程序開啟的每一個檔案的連結 |
maps | 與程序相關的記憶體對映資訊 |
mem | 包含了程序在記憶體中的內容 |
stat | 包含了程序的狀態資訊 |
statm | 包含了程序的記憶體使用資訊 |
limits | 儲存了程序的軟限制,硬限制等資訊 |
root | 指向程序根目錄的軟連結 |
self | 連結到當前正在執行的程序 |
task | 包含當前程序所有子執行緒pid |
其他更多介紹建議參考man-proc。
說明一點,我使用的是Huawei Mate9的adb shell。
例如以下是cat limits
的輸出結果:
# cat limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 11590 11590 processes
Max open files 1024 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 11590 11590 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 40 40
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
對於CPU佔用情況,你可以使用top或ps直接獲取,當然你可以參考通過/proc/stat等檔案計算Cpu使用率。
對於記憶體佔用情況,可以直接通過檢視cat /proc/pid/status
獲得,比如下面的一個輸出:
Name: al.simpleplayer
State: S (sleeping)
Tgid: 12041
Ngid: 0
Pid: 12041
PPid: 467
TracerPid: 0
Uid: 10127 10127 10127 10127
Gid: 10127 10127 10127 10127
FDSize: 256
Groups: 3003 9997 50127
VmPeak: 3010472 kB
VmSize: 2884308 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 948344 kB
VmRSS: 916964 kB
VmData: 1518672 kB
VmStk: 8196 kB
VmExe: 20 kB
VmLib: 136604 kB
VmPTE: 3824 kB
VmPMD: 16 kB
VmSwap: 4 kB
Threads: 380
SigQ: 0/11590
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000001204
SigIgn: 0000000000000000
SigCgt: 200000020000c4fa
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000000000000000
CapAmb: 0000000000000000
Seccomp: 0
Cpus_allowed: ff
Cpus_allowed_list: 0-7
Mems_allowed: 1
Mems_allowed_list: 0
voluntary_ctxt_switches: 407399
nonvoluntary_ctxt_switches: 315236
記憶體相關的都是Vm打頭的,解釋如下:
VmPeak: 60184 kB 程序地址空間的大小
VmHWM: 18020 kB 檔案記憶體對映和匿名記憶體對映的大小
VmSize(KB)=1499136 任務虛擬地址空間的大小 (total_vm-reserved_vm),其中total_vm為程序的地址空間的大小,reserved_vm:程序在預留或特殊的記憶體間的物理頁
VmLck(KB)=0 任務已經鎖住的實體記憶體的大小。鎖住的實體記憶體不能交換到硬碟 (locked_vm)
VmRSS(KB)= 344 kB 應用程式正在使用的實體記憶體的大小,就是用ps命令的引數rss的值 (rss)
VmData(KB)=20KB 程式資料段的大小(所佔虛擬記憶體的大小),存放初始化了的資料; (total_vm-shared_vm-stack_vm)
VmStk(KB)=84KB 任務在使用者態的棧的大小 (stack_vm)
VmExe(KB)=4KB 程式所擁有的可執行虛擬記憶體的大小,程式碼段,不包括任務使用的庫 (end_code-start_code)
VmLib(KB)=1300KB 被映像到任務的虛擬記憶體空間的庫的大小 (exec_lib)
VmPTE=6KB 該程序的所有頁表的大小,單位:kb
該程序已開啟控制代碼(fd)可以使用ls -l /proc/pid/fd/
,輸出為詳細內容:
# ls -l fd
total 0
lrwx------ 1 u0_a127 u0_a127 64 2018-03-02 17:31 0 -> /dev/null
lrwx------ 1 u0_a127 u0_a127 64 2018-03-02 17:31 1 -> /dev/null
lr-x------ 1 u0_a127 u0_a127 64 2018-03-02 17:31 10 -> /system/etc/event-log-tags
lr-x------ 1 u0_a127 u0_a127 64 2018-03-02 17:31 11 -> /system/framework/core-oj.jar
lrwx------ 1 u0_a127 u0_a127 64 2018-03-02 17:31 26 -> anon_inode:[eventfd]
l-wx------ 1 u0_a127 u0_a127 64 2018-03-02 17:31 27 -> /dev/cpuctl/tasks
lrwx------ 1 u0_a127 u0_a127 64 2018-03-02 17:31 3 -> socket:[17762]
l-wx------ 1 u0_a127 u0_a127 64 2018-03-02 17:31 33 -> pipe:[275546]
lrwx------ 1 u0_a127 u0_a127 64 2018-03-02 17:28 43 -> /storage/emulated/0/render.log
程序內部包含的執行緒詳細資訊可以在/proc/pid/task
目錄中檢視,統計數目可以在cat /proc/pid/status
獲得。
3 網路資源監控
關於網路資源佔用的資訊,linux下提供了很多工具,比如netstat、iftop、ntop、nethogs、ifstat等等。可以按照程序、埠、裝置統計具體流量。如果大家對其中某個工具感興趣可以檢視對應的資料。
這裡我們介紹下如何通過/proc/pid/目錄拿到特定程序已開啟的socket及其屬性(udp、tcp、佔用埠等)。
在/proc/pid/fd
目錄下可以看到當前程序開啟多少個socket(socket也屬於fd的一種)。更具體的資訊可以在/proc/pid/net/tcp
或/proc/pid/net/udp
,輸出資訊如下:
hi3660:/proc/24495/net # cat tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 0100007F:13AD 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 9672 1 fffffff5cc160000 100 0 0 10 0
1: CD340A0A:DB24 AB66387B:0050 06 00000000:00000000 03:00000B7B 00000000 0 0 0 3 fffffff597baad68
2: CD340A0A:DADE AB66387B:0050 06 00000000:00000000 03:0000051B 00000000 0 0 0 3 fffffff597baaa50
3: CD340A0A:DAC2 AB66387B:0050 06 00000000:00000000 03:000004A2 00000000 0 0 0 3 fffffff597baa108
4: CD340A0A:DBBA AB66387B:0050 06 00000000:00000000 03:0000171C 00000000 0 0 0 3 fffffff597baa000
5: CD340A0A:DBB4 AB66387B:0050 08 00000000:00000000 00:00000000 00000000 10129 0 960411 1 fffffff59f790000 20 4 32 10 7
6: CD340A0A:DBC4 AB66387B:0050 01 00000000:00000000 00:00000000 00000000 10129 0 971487 1 fffffff599916600 21 4 30 10 7
7: CD340A0A:DBB2 AB66387B:0050 06 00000000:00000000 03:00001713 00000000 0 0 0 3 fffffff597baa948
8: CD340A0A:DBA8 AB66387B:0050 06 00000000:00000000 03:0000170A 00000000 0 0 0 3 fffffff597baa528
9: CD340A0A:DBB6 AB66387B:0050 06 00000000:00000000 03:00001718 00000000 0 0 0 3 fffffff597baa420
10: CD340A0A:DB0C AB66387B:0050 06 00000000:00000000 03:000009F5 00000000 0 0 0 3 fffffff597baa630
11: CD340A0A:DBB8 AB66387B:0050 06 00000000:00000000 03:0000171A 00000000 0 0 0 3 fffffff597baa738
這和netstat輸出是一致的。
hi3660:/proc/24495/net # netstat -tu
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 10.10.52.205:56100 123.56.102.171:http TIME_WAIT
tcp 0 0 10.10.52.205:56308 123.56.102.171:http ESTABLISHED
tcp 0 0 10.10.52.205:56030 123.56.102.171:http TIME_WAIT
tcp 0 0 10.10.52.205:56284 123.56.102.171:http CLOSE_WAIT
tcp 0 0 10.10.52.205:56002 123.56.102.171:http TIME_WAIT
tcp 0 0 10.10.52.205:56250 123.56.102.171:http TIME_WAIT
tcp 0 0 10.10.52.205:56242 123.56.102.171:http TIME_WAIT
tcp 0 0 10.10.52.205:56232 123.56.102.171:http TIME_WAIT
tcp 0 0 10.10.52.205:56246 123.56.102.171:http TIME_WAIT
tcp 0 0 10.10.52.205:56076 123.56.102.171:http TIME_WAIT
tcp 0 0 10.10.52.205:56248 123.56.102.171:http TIME_WAIT
5 總結
本文的主要目標是簡單地瞭解下linux下程序的構成,可以通過命令列直接檢視程序內部已開啟資源,對於實際除錯中資源洩露有所幫助。