分享

linux 程序分析工具

 心不留意外尘 2016-06-05

http://blog.csdn.net/denny_233/article/details/7477282

2012

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

 

写在最前面:在开始本文之前,笔者认为先有必要介绍一下linux下的man,如果读者手头用linux系统,直接在终端输入man man便可以看到详细的说明,我在这里简单的总结一下,man命令是用来查看linux下各种命令、工具等的用户手册(manual)的。一种比较常用的用法是”man n field”,这里的n是要查找的手册了类型,field是关键字。在这里介绍一下n:

  • 0 /usr/include下的头文件
  • 1 可执行程序和shell命令
  • 2 系统调用
  • 3 系统库函数
  • 4 /dev下的特殊文件
  • 5 文件格式和约定(比如/etc/passwd)

  • 6 游戏
  • 7 其它
  • 8 仅root可用的系统管理命令
  • 9 内核相关的内容

          通常情况下,如果不加n的话,系统会按一定的顺序,有时候得到的可能不是你想要的,这时候就需要加上n了,这就是我要介绍n的目的。比如,你man printf,系统返回的肯定是shell命令printf,你要看库函数printf怎么办呢,那就man 3 printf,that’s ok :razz:
          下面进入今天的正题,/proc是linux系统为我们用户提供的一个可以用来访问系统相关数据及信息的一个伪文件 系统,通过它我们不仅可以获取指定某个进程的相关信息,还可以获取系统整体的运行情况及信息。因为本文讲的是分析程序的工具,所以本文将侧重介绍通过/proc来分析程序本身,关于如何通过/proc来查看系统相关信息,可以通过man 5 proc来看(这也是我开始就讲man的一个原因 :razz: )。

  • /proc/[number]/cmdline 程序命令行参数,以’\0′分隔的字符串文件(在程序中,可以通过直接读此文件,获取程序的命令行参数,但不推荐这么做,这样做了程序的可移植性不好 :cry:
  • /proc/[number]/cwd 程序的当前工作路径的软链接(readlink就可以得到被链接的目录)
  • /proc/[number]/environ 程序的当前环境变量,以’\0′分隔的字符串文件
  • /proc/[number]/exe 程序的可执行文件的软链接(通过readlink可以获取程序可执行文件的完整路径)
  • /proc/[number]/fd 程序当前正在使用的fd,这些fd都链向实际的文件
  • /proc/[number]/maps 程序的地址空间分布和访问权限(通过这些信息,可以查看进程的地址是否在合法的范围)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    address           perms offset  dev   inode      pathname
    08048000-08056000 r-xp 00000000 03:0c 64593      /usr/sbin/gpm
    08056000-08058000 rw-p 0000d000 03:0c 64593      /usr/sbin/gpm
    08058000-0805b000 rwxp 00000000 00:00 0
    40000000-40013000 r-xp 00000000 03:0c 4165       /lib/ld-2.2.4.so
    40013000-40015000 rw-p 00012000 03:0c 4165       /lib/ld-2.2.4.so
    4001f000-40135000 r-xp 00000000 03:0c 45494      /lib/libc-2.2.4.so
    40135000-4013e000 rw-p 00115000 03:0c 45494      /lib/libc-2.2.4.so
    4013e000-40142000 rw-p 00000000 00:00 0
    bffff000-c0000000 rwxp 00000000 00:00 0
  • /proc/[number]/smaps (since Linux 2.6.14) 程序的每块内存映射区域的内存使用情况
    1
    2
    3
    4
    5
    6
    7
    
    08048000-080bc000 r-xp 00000000 03:02 13130 /bin/bash    #与maps中的相同
    Size:               464 kB                       #映射区的大小
    Rss:                424 kB                       #实际在内存中的大小
    Shared_Clean:       424 kB 
    Shared_Dirty:         0 kB
    Private_Clean:        0 kB
    Private_Dirty:        0 kB
  • /proc/[number]/stat 程序的状态信息,ps命令得到的程序信息就是从此处获取的,因此详细的因容可以ps命令
  • /proc/[number]/statm 程序的内存页(page)状态
    1
    2
    3
    4
    5
    6
    7
    
    size       total program size
    resident   resident set size
    share      shared pages
    text       text (code)
    lib        library
    data       data/stack
    dt         dirty pages (unused in Linux 2.6)
  • /proc/[number]/status stat和statm合起来的信息,以一种比较方便用户读的方式展示

  • 原创文章,转载请注明出处:小武哥的博客

    本文固定链接:http://www./?p=1517


    linux程序分析工具介绍(二)—-ldd,nm

    本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具。ldd是用来分析程序运行时需要依赖的动态库的工具;nm是用来查看指定程序中的符号表相关内容的工具。下面通过例子,分别来介绍一下这两个工具:

    1. ldd, 先看下面的例子, 用ldd查看cs程序所依赖的动态库:

    wuzesheng@wuzesheng-ubuntu:~/Public$ ldd cs
    	linux-gate.so.1 =>  (0xffffe000)
    	libz.so.1 => /lib/libz.so.1 (0xb7f8c000)
    	libpthread.so.0 => /lib/libpthread.so.0 (0xb7f75000)
    	libcrypto.so.0.9.8 => /usr/lib/libcrypto.so.0.9.8 (0xb7e4d000)
    	libpcre.so.0 => /usr/lib/libpcre.so.0 (0xb7e21000)
    	libstdc++.so.6 => /usr/local/gcc4.5.1/lib/libstdc++.so.6 (0xb7d40000)
    	libm.so.6 => /lib/libm.so.6 (0xb7d18000)
    	libgcc_s.so.1 => /usr/local/gcc4.5.1/lib/libgcc_s.so.1 (0xb7cfd000)
    	libc.so.6 => /lib/libc.so.6 (0xb7bbc000)
    	/lib/ld-linux.so.2 (0xb7fab000)
    	libdl.so.2 => /lib/libdl.so.2 (0xb7bb7000)


    在上面的例子中,ldd的结果可以分为三列来看:

  • 第一列:程序需要依赖什么库
  • 第二列: 系统提供的与程序需要的库所对应的库
  • 第三列:库加载的开始地址

    通过上面的信息,我们可以得到以下几个信息:

  • (1) 通过对比第一列和第二列,我们可以分析程序需要依赖的库和系统实际提供的,是否相匹配
  • (2) 通过观察第三列,我们可以知道在当前的库中的符号在对应的进程的地址空间中的开始位置

    2. nm, 通过下面的例子,我们来介绍nm工具:
    先看一下这个简单的程序:

    1. <span style="color:#339900">#include "iostream"</span>  
    2.    
    3. <span style="color:#0000ff">using</span> <span style="color:#0000ff">namespace</span> std<span style="color:#008080">;</span>  
    4.    
    5. <span style="color:#0000ff">class</span> Test  
    6. <span style="color:#008000">{</span>  
    7. <span style="color:#0000ff">public</span><span style="color:#008080">:</span>  
    8.     <span style="color:#0000ff">void</span> Hello<span style="color:#008000">(</span><span style="color:#008000">)</span>  
    9.     <span style="color:#008000">{</span>  
    10.         <span style="color:#0000dd">cout</span> <span style="color:#000080"><</span> <span style="color:#000080"><</span> <span style="color:#FF0000">"Hello world!"</span> <span style="color:#000080"><<</span> endl<span style="color:#008080">;</span>  
    11.     <span style="color:#008000">}</span>  
    12. <span style="color:#008000">}</span><span style="color:#008080">;</span>  
    13.    
    14. <span style="color:#0000ff">int</span> main<span style="color:#008000">(</span><span style="color:#008000">)</span>  
    15. <span style="color:#008000">{</span>  
    16.     Test test<span style="color:#008080">;</span>  
    17.     test.<span style="color:#007788">Hello</span><span style="color:#008000">(</span><span style="color:#008000">)</span><span style="color:#008080">;</span>  
    18. <span style="color:#008000">}</span>  

    接下来,我们编译该程序,然后看nm的结果:

    wuzesheng@wuzesheng-ubuntu:~/Public$ g++ test.cc -o test
    wuzesheng@wuzesheng-ubuntu:~/Public$ nm test
    08049f10 d _DYNAMIC
    08049ff4 d _GLOBAL_OFFSET_TABLE_
    080486f0 t _GLOBAL__I_main
    080487fc R _IO_stdin_used
             w _Jv_RegisterClasses
    080486b0 t _Z41__static_initialization_and_destruction_0ii
    0804870c W _ZN4Test5HelloEv
             U _ZNSolsEPFRSoS_E@@GLIBCXX_3.4
             U _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
             U _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
    0804a040 B _ZSt4cout@@GLIBCXX_3.4
             U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@@GLIBCXX_3.4
    0804a0d4 b _ZStL8__ioinit
             U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@@GLIBCXX_3.4
    08049f00 d __CTOR_END__
    08049ef8 d __CTOR_LIST__
    08049f08 D __DTOR_END__
    08049f04 d __DTOR_LIST__
    080488c8 r __FRAME_END__
    08049f0c d __JCR_END__
    08049f0c d __JCR_LIST__
    0804a02c A __bss_start
             U __cxa_atexit@@GLIBC_2.1.3
    0804a024 D __data_start
    080487b0 t __do_global_ctors_aux
    08048610 t __do_global_dtors_aux
    0804a028 D __dso_handle
             w __gmon_start__
             U __gxx_personality_v0@@CXXABI_1.3
    080487aa T __i686.get_pc_thunk.bx
    08049ef8 d __init_array_end
    08049ef8 d __init_array_start
    08048740 T __libc_csu_fini
    08048750 T __libc_csu_init
             U __libc_start_main@@GLIBC_2.0
    0804a02c A _edata
    0804a0d8 A _end
    080487dc T _fini
    080487f8 R _fp_hw
    08048508 T _init
    080485e0 T _start
    0804a0cc b completed.7065
    0804a024 W data_start
    0804a0d0 b dtor_idx.7067
    08048670 t frame_dummy
    08048694 T main

    上面便是test这个程序中所有的符号,首先需要介绍一下上面的内容的格式:

  • 第一列:当前符号的地址
  • 第二列:当前符号的类型(关于类型的说明,感兴趣的朋友可以man nm详阅)
  • 第三列:当前符号的名称

    在上面的结果中,像_ZN4Test5HelloEv这样的符号,很多读者朋友可能会被它搞晕,这里介绍个小技巧,在nm的时候,加上-C选项,就可以把这些难以识别的符号,转换成便于我们阅读的符号TestHello()。这个主要是c++中的mangle机制所导致的,加上-C就是指定列出的符号是demangle了的。说了这么多,到底nm对我们程序有啥具体的帮助呢,我觉得主要有以下几个方面:
    (1)判断指定程序中有没有定义指定的符号 (比较常用的方式:nm -C proc | grep symbol)
    (2)解决程序编译时undefined reference的错误,以及mutiple definition的错误
    (3)查看某个符号的地址,以及在进程空间的大概位置(bss, data, text区,具体可以通过第二列的类型来判断)

  • 原创文章,转载请注明出处:小武哥的博客
    本文固定链接:http://www./?p=1595



    linux程序分析工具介绍(三)——sar

    本文要介绍的sar,是linux下用来分析系统本身运行情况的非常有用的工具。我们知道,程序在操作系统上要运行,要关注的点不外乎内存,CPU和IO(包括磁盘IO和网络IO)。我们的应用程序在操作系统中运行前,我们需要了解系统当前的内存,cpu和IO的使用状况,还需要明白我们的应用程序运行时自身所需要的内存,cpu和IO资源的情况。只有操作系统剩余的内存,cpu和IO资源能够满足应用程序所需要的,才能保证应用程序在操作系统中正常的运行。sar就是用来帮助我们了解操作系统当前内存,cpu和IO等资源的使用情况的一个非常方便的工具,下面通过具体的例子来介绍sar的使用。
          在介绍例子之前,首先需要说一下sar命令的基本用法:sar [option] [interval] [count]
  • 1. 通过sar获取系统内存使用相关信息

    (1)内存使用情况统计:-r,通过这个选项,我们可以了解当前系统中内存的使用情况

    1
    2
    3
    4
    5
    6
    7
    8
    
    wuzesheng@ubuntu:~/work/test$ sar -r 1 3
    Linux 2.6.38-8-generic (ubuntu) 	07/09/2011 	_i686_	(2 CPU)
     
    06:33:01 PM kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact
    06:33:02 PM    458664    566488     55.26     96268    265056   1034780     49.95    262500    254888
    06:33:03 PM    458664    566488     55.26     96268    265056   1034780     49.95    262468    254888
    06:33:04 PM    458696    566456     55.26     96268    265056   1034780     49.95    262468    254888
    Average:       458675    566477     55.26     96268    265056   1034780     49.95    262479    254888

          请看上面的例子,sar -r 1 3 表示时间间隔为1秒,统计3次,最后一行为3次的均值。
    (2)换页统计:-B,通过这个选项,我们可以了解当前系统中,页交换的情况

    1
    2
    3
    4
    5
    6
    7
    8
    
    wuzesheng@ubuntu:~/work/test$ sar -B 1 3
    Linux 2.6.38-8-generic (ubuntu) 	07/09/2011 	_i686_	(2 CPU)
     
    06:56:48 PM  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff
    06:56:49 PM      0.00      0.00   1438.00      0.00   3001.00      0.00      0.00      0.00      0.00
    06:56:50 PM      0.00      0.00    796.00      0.00   1620.00      0.00      0.00      0.00      0.00
    06:56:51 PM      0.00      0.00    770.00      0.00   1580.00      0.00      0.00      0.00      0.00
    Average:         0.00      0.00   1001.33      0.00   2067.00      0.00      0.00      0.00      0.00

          上面是每1秒统计一次,统计3次的结果,最后一行为3次的均值。
          以上便是关于内存的比较关键的两个指标,通过上面两个选项,系统内存使用相关的情况可以一目了然。

  • 2. 通过sar获取系统cpu使用相关信息

    (1)CPU总体使用情况统计:-u, 用法为sar -u [ALL] [interval] [count], 加上ALL表示列出所有的关于cpu的统计项,如果不加ALL的话,只列一些比较常用的指标:

    1
    2
    3
    4
    5
    6
    7
    8
    
    wuzesheng@ubuntu:~/work/test$ sar -u ALL 1 3 
    Linux 2.6.38-8-generic (ubuntu) 	07/09/2011 	_i686_	(2 CPU)
     
    07:21:08 PM     CPU      %usr     %nice      %sys   %iowait    %steal      %irq     %soft    %guest     %idle
    07:21:09 PM     all      1.01      0.00      1.01      0.00      0.00      0.00      0.00      0.00     97.98
    07:21:10 PM     all      0.50      0.00      1.00      0.00      0.00      0.00      0.00      0.00     98.51
    07:21:11 PM     all      0.99      0.00      0.99      0.00      0.00      0.00      0.00      0.00     98.02
    Average:        all      0.83      0.00      1.00      0.00      0.00      0.00      0.00      0.00     98.17

          上面是每1秒统计一次,统计3次后的的结果,最后一行为3次的平均值。
    (2)每个CPU的单独的统计: -P,用法为sar -P { cpu [,...] | ALL } [interval] [count],这里第二个参数可以指定cpu序号,来查看指定的cpu,或者指定ALL,查看所有cpu的统计:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    
    wuzesheng@ubuntu:~/work/test$ sar -P 0 1 3
    Linux 2.6.38-8-generic (ubuntu) 	07/09/2011 	_i686_	(2 CPU)
     
    07:44:42 PM     CPU     %user     %nice   %system   %iowait    %steal     %idle
    07:44:43 PM       0      1.06      0.00      2.13      0.00      0.00     96.81
    07:44:44 PM       0      0.00      0.00      0.97      0.00      0.00     99.03
    07:44:45 PM       0      0.97      0.00      1.94      0.00      0.00     97.09
    Average:          0      0.67      0.00      1.67      0.00      0.00     97.67
    wuzesheng@ubuntu:~/work/test$ sar -P ALL 1 3
    Linux 2.6.38-8-generic (ubuntu) 	07/09/2011 	_i686_	(2 CPU)
     
    07:46:01 PM     CPU     %user     %nice   %system   %iowait    %steal     %idle
    07:46:02 PM     all      1.51      0.00      3.52      0.00      0.00     94.97
    07:46:02 PM       0      3.00      0.00      6.00      0.00      0.00     91.00
    07:46:02 PM       1      0.00      0.00      2.00      0.00      0.00     98.00
     
    07:46:02 PM     CPU     %user     %nice   %system   %iowait    %steal     %idle
    07:46:03 PM     all      1.01      0.00      1.52      0.00      0.00     97.47
    07:46:03 PM       0      1.04      0.00      2.08      0.00      0.00     96.88
    07:46:03 PM       1      0.00      0.00      0.00      0.00      0.00    100.00
     
    07:46:03 PM     CPU     %user     %nice   %system   %iowait    %steal     %idle
    07:46:04 PM     all      0.00      0.00      1.50      0.00      0.00     98.50
    07:46:04 PM       0      1.00      0.00      3.00      0.00      0.00     96.00
    07:46:04 PM       1      0.00      0.00      0.00      0.00      0.00    100.00
     
    Average:        CPU     %user     %nice   %system   %iowait    %steal     %idle
    Average:        all      0.84      0.00      2.18      0.00      0.00     96.98
    Average:          0      1.69      0.00      3.72      0.00      0.00     94.59
    Average:          1      0.00      0.00      0.67      0.00      0.00     99.33

          上面是每1秒统计一次,统计3次后的的结果,最后一行为3次的平均值。我们可以看出,这里每个CPU的情况都列的非常清楚。
          通过上面两个选项,关于CPU的基本使用情况,都一目了然了。

  • 3. 通过sar获取系统IO信息

    (1)磁盘设备IO情况统计:-b, 用来统计对物理设备的IO状态,主要是磁盘IO

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    wuzesheng@ubuntu:~/work/test$ sar -b 1 10
    Linux 2.6.38-8-generic (ubuntu) 	07/09/2011 	_i686_	(2 CPU)
     
    07:55:30 PM       tps      rtps      wtps   bread/s   bwrtn/s
    07:55:31 PM      0.00      0.00      0.00      0.00      0.00
    07:55:32 PM      0.00      0.00      0.00      0.00      0.00
    07:55:33 PM      0.00      0.00      0.00      0.00      0.00
    07:55:34 PM      0.00      0.00      0.00      0.00      0.00
    07:55:35 PM      6.00      0.00      6.00      0.00    112.00
    07:55:36 PM      0.00      0.00      0.00      0.00      0.00
    07:55:37 PM      0.00      0.00      0.00      0.00      0.00
    07:55:38 PM      0.00      0.00      0.00      0.00      0.00
    07:55:39 PM      0.00      0.00      0.00      0.00      0.00
    07:55:40 PM     10.00      0.00     10.00      0.00     80.00
    Average:         1.60      0.00      1.60      0.00     19.20

    (2)网络设备IO情况统计:-n, 用法sar -n { keyword [,...] | ALL }, keyword包括DEV, EDEV, NFS, NFSD, SOCK, IP, EIP, ICMP, EICMP, TCP, ETCP, UDP, SOCK6, IP6, EIP6, ICMP6, EICMP6 和 UDP6,不同的keyword统计不同的方面,关于网络IO的统计主要是用DEV,看每个设备上的读写情况:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    wuzesheng@ubuntu:~/work/test$ sar -n DEV 1 3
    Linux 2.6.38-8-generic (ubuntu) 	07/09/2011 	_i686_	(2 CPU)
     
    08:05:33 PM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
    08:05:34 PM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
    08:05:34 PM      eth0      0.00      0.00      0.00      0.00      0.00      0.00      0.00
     
    08:05:34 PM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
    08:05:35 PM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
    08:05:35 PM      eth0      0.00      0.00      0.00      0.00      0.00      0.00      0.00
     
    08:05:35 PM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
    08:05:36 PM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
    08:05:36 PM      eth0      0.00      0.00      0.00      0.00      0.00      0.00      0.00
     
    Average:        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
    Average:           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
    Average:         eth0      0.00      0.00      0.00      0.00      0.00      0.00      0.00

          上面是每1秒统计1次,统计3次的结果,最后几列为均值。
          通过上述选项,关于磁盘IO和网络IO的情况便可以一目了然。
          通过本文的内容,关于内存、cpu、IO的情况,我们便可以清楚的了解,其实,在linux下有很多工具可以完成上面的功能,只不过sar是相对比较全面的工具,所以在这里重点介绍了一下。其它的工具,包括vmstat可以用来查看内存的使用情况,top可以用来查看cpu的使用情况,iostat可以用来查看io的情况。说到底,用什么工具不是关键,解决问题才是我们的目的。另外,了解了这些工具的用法,还要学会如何使用它们去解决实际的问题,这是最重要的,后续我将就如何通过这些工具来优化应用程序写几篇文章,分享给大家,敬请期待。

  • 原创文章,转载请注明出处:小武哥的博客
    本文固定链接:http://www./?p=1657

      本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
      转藏 分享 献花(0

      0条评论

      发表

      请遵守用户 评论公约

      类似文章 更多