官术网_书友最值得收藏!

3.4.2 調試的方法

由于Android系統(tǒng)基于Linux,Android中的調試方式首先可以利用標準Linux的基本調試的方法,除此之外,Android中還有特定的調試方法。

1.查看系統(tǒng)進程的情況

首先可以在終端使用ps命令查看系統(tǒng)的進程。啟動Android的仿真器環(huán)境,然后使用adb shell進行連接,使用ps查看各個進程,如下所示:

    # ps
    USER     PID   PPID  VSIZE  RSS     WCHAN    PC         NAME
    root      1     0     312    220   c009b74c 0000ca4c S /init
    root      2     0     0      0     c004e72c 00000000 S kthreadd
    root      3     2     0      0     c003fdc8 00000000 S ksoftirqd/0
    root      4     2     0      0     c004b2c4 00000000 S events/0
    root      5     2     0      0     c004b2c4 00000000 S khelper
    root      6     2     0      0     c004b2c4 00000000 S suspend
    root      7     2     0      0     c004b2c4 00000000 S kblockd/0
    root      8     2     0      0     c004b2c4 00000000 S cqueue
    root      9     2     0      0     c018179c 00000000 S kseriod
    root      10    2     0      0     c004b2c4 00000000 S kmmcd
    root      11    2     0      0     c006fc74 00000000 S pdflush
    root      12    2     0      0     c006fc74 00000000 S pdflush
    root      13    2     0      0     c00744e4 00000000 S kswapd0
    root      14    2     0      0     c004b2c4 00000000 S aio/0
    root      22    2     0      0     c017ef48 00000000 S mtdblockd
    root      23    2     0      0     c004b2c4 00000000 S kstriped
    root      24    2     0      0     c004b2c4 00000000 S hid_compat
    root      25    2     0      0     c004b2c4 00000000 S rpciod/0
    root      26    2     0      0     c019d16c 00000000 S mmcqd
    root      27    1     740    220   c0158eb0 afd0d8ac S /system/bin/sh
    system    28    1     808    208   c01a94a4 afd0db4c S /system/bin/servicemanager
    root      29    1     3736   372   ffffffff afd0e1bc S /system/bin/vold
    root      30    1     3716   316   ffffffff afd0e1bc S /system/bin/netd
    root      31    1     668    184   c01b52b4 afd0e4dc S /system/bin/debuggerd
    radio     32    1     5392   480   ffffffff afd0e1bc S /system/bin/rild
    root      33    1     81940  22164 c009b74c afd0dc74 S zygote
    media     34    1     19508  1836  ffffffff afd0db4c S /system/bin/mediaserver
    bluetooth 35    1     1260   288   c009b74c afd0e98c S /system/bin/dbus-daemon
    root      36    1     812    236   c02181f4 afd0d8ac S /system/bin/installd
    keystore  37    1     1616   216   c01b52b4 afd0e4dc S /system/bin/keystore
    root      38    1     740    220   c003da38 afd0e7bc S /system/bin/sh
    root      39    1     840    280   c00b8fec afd0e90c S /system/bin/qemud
    root      41    1     3384   176   ffffffff 0000ecc4 S /sbin/adbd
    root      54    38    796    248   c02181f4 afd0d8ac S /system/bin/qemu-props
    system    62    33    152636 30928 ffffffff afd0db4c S system_server
    app_9     121   33    108964 18128 ffffffff afd0eb08 S com.android.inputmethod.latin
    radio     125   33    120308 19396 ffffffff afd0eb08 S com.android.phone
    app_27    128   33    108092 21528 ffffffff afd0eb08 S com.android.launcher
    system    131   33    109420 16932 ffffffff afd0eb08 S com.android.settings
    app_8     157   33    118524 22096 ffffffff afd0eb08 S android.process.acore
    app_0     182   33    116196 17064 ffffffff afd0eb08 S com.android.mms
    app_16    188   33    104244 17520 ffffffff afd0eb08 S android.process.media
    app_6     207   33    106856 18020 ffffffff afd0eb08 S com.android.email
    app_10    218   33    103260 16800 ffffffff afd0eb08 S com.android.bluetooth
    app_12    226   33    10421617020ffffffffafd0eb08Scom.android.providers.calendar
    app_15    240   33    103028 16900 ffffffff afd0eb08 S com.android.deskclock
    app_3     248   33    102408 15832 ffffffff afd0eb08 S com.android.protips
    app_4     255   33    105144 16748 ffffffff afd0eb08 S com.android.quicksearchbox
    app_13    262   33    103452 16164 ffffffff afd0eb08 S com.android.music
    root      268   41    740    328   c003da38 afd0e7bc S /system/bin/sh
    root      282   268   888    332   00000000 afd0d8ac R ps

從Android系統(tǒng)的進程中可以看到,1號和2號進程以0號進程為父進程。init是系統(tǒng)運行的第1個用戶空間進程,即Android根目下的init可執(zhí)行程序,這是一個用戶空間的進程。kthreadd是系統(tǒng)的2號進程,這是一個內核進程,其他內核進程都直接或間接以kthreadd為父進程。

系統(tǒng)的各個守護進行由init進行運行,例如Zygote、/system/bin/sh、/system/bin/mediaserver、/system/bin/adbd等,因此它們的父進程號為1,即以init為父進程。

各種文字名稱的進程表示Android應用程序的進程,例如android.process.acore、com.android.mms等進程代表的是應用程序進程,它們的父進程都是zygote。例如,在本例中它們的父進程id均為33。

本例中ps命令的進城id為282,其父進程是pid為268的/system/bin/sh,可見這個命令是從sh分支出來的,而pid為268的/system/bin/sh的父進程是pid為41的/system/bin/adbd (adb守護進程)。

使用Linux的proc文件系統(tǒng),也可以查看進程相關的信息,在/proc目錄中,包含了各個進程的信息,每個進程一個目錄,就是進程的id。

例如,查看27號進程的目錄如下所示:

    # ls -l /proc/27/
    dr-xr-xr-x root     root               2010-08-13 03:39 task
    dr-x------ root     root               2010-08-13 03:39 fd
    dr-x------ root     root               2010-08-13 03:39 fdinfo
    dr-xr-xr-x root     root               2010-08-13 03:39 net
    -r-------- root     root             0 2010-08-13 03:39 environ
    -r-------- root     root             0 2010-08-13 03:39 auxv
    -r--r--r-- root     root             0 2010-08-13 03:39 status
    -r-------- root     root             0 2010-08-13 03:39 personality
    -r-------- root     root             0 2010-08-13 03:39 limits
    -rw-r--r-- root     root             0 2010-08-13 03:39 sched
    -r--r--r-- root     root             0 2010-08-13 03:38 cmdline
    -r--r--r-- root     root             0 2010-08-13 03:34 stat
    -r--r--r-- root     root             0 2010-08-13 03:39 statm
    -r--r--r-- root     root             0 2010-08-13 03:39 maps
    -rw------- root     root             0 2010-08-13 03:39 mem
    lrwxrwxrwx root     root               2010-08-13 03:39 cwd -> /
    lrwxrwxrwx root     root               2010-08-13 03:39 root -> /
    lrwxrwxrwx root     root               2010-08-13 03:39 exe -> /system/bin/sh
    -r--r--r-- root     root             0 2010-08-13 03:39 mounts
    -r--r--r-- root     root             0 2010-08-13 03:39 mountinfo
    -r-------- root     root             0 2010-08-13 03:39 mountstats
    --w------- root     root             0 2010-08-13 03:39 clear_refs
    -r--r--r-- root     root             0 2010-08-13 03:39 smaps
    -r-------- root     root             0 2010-08-13 03:39 pagemap
    -r--r--r-- root     root             0 2010-08-13 03:39 wchan
    -r--r--r-- root     root             0 2010-08-13 03:39 schedstat
    -r--r--r-- root     root             0 2010-08-13 03:39 cgroup
    -r--r--r-- root     root             0 2010-08-13 03:39 oom_score
    -rw-r--r-- root     root             0 2010-08-13 03:39 oom_adj
    -rw-r--r-- root     root             0 2010-08-13 03:39 coredump_filter

在每個進程的目錄中,包含了若干個文件的子目錄,其中cmdline文件表示了這個進程所在的命令行:

    # cat /proc/27/cmdline
    /system/bin/sh

由此可見,這個27號進程就是shell程序。查看status文件,可以獲知這個進程的一些相關信息。對27號進程的查看如下所示:

    # cat /proc/27/status
    Name:     sh                                   # 進程名稱
    State:   S (sleeping)                       # 進程狀態(tài)
    Tgid:     27                                   # 線程組ID
    Pid:      27                                   # 進程ID
    PPid:     1                                    # 父進程ID
    TracerPid:    0
    Uid:0    0    0    0
    Gid:0    0    0    0
    FDSize:  1024
    Groups:
    VmPeak:       744 kB                         # 虛擬內存相關消息
    VmSize:        744 kB
    VmLck:           0 kB
    VmHWM:         316 kB
    VmRSS:         264 kB
    VmData:         92 kB
    VmStk:          84 kB
    VmExe:          80 kB
    VmLib:         460 kB
    VmPTE:          12 kB
    Threads: 1                                    # 所包含的線程數(shù)
    SigQ:     0/768
    SigPnd:  0000000000000000
    ShdPnd:  0000000000000000
    SigBlk:  0000000000000000
    SigIgn:  0000000000284004
    SigCgt:  00000000000094ea
    CapInh:  0000000000000000
    CapPrm:  fffffffffffffeff
    CapEff:  fffffffffffffeff
    CapBnd:  fffffffffffffeff
    voluntary_ctxt_switches:   38
    nonvoluntary_ctxt_switches:     1

stat文件實際上包含了比status文件更多的信息,但是可讀性比較差,因此一般查看status文件。

進程目錄中的fd文件,表示了這個進程中所打開的文件的描述符。對27號進程的查看如下所示:

    # ls /proc/27/fd
    0
    1
    2
    9
    1023

進程目錄中的task目錄表示了這個進程所包含的子進程,也就是這個進程中所包含的線程,目錄的名稱也就是子進程的id。對27號進程的查看如下所示:

    # ls /proc/27/task
    27

27號進程只包含一個進程,即27號進程自己。

在Linux操作系統(tǒng)的內核的角度出發(fā),進程和線程沒有區(qū)別。在用戶空間建立的線程(例如,通過pthread建立的)在內核的情況就是一個進程,也就是上述的子進程。事實上,這些子進程的目錄結構和進程是一樣的。

對于34號進程mediaserver,情況如下所示:

    # cat /proc/34/cmdline
    /system/bin/mediaserver
    # ls
    34
    58
    59
    60
    61
    98

除了34之外,還包含了58,59,60,61,98這4個文件夾,由此可見,mediaserver進程已經包含了若干個子進程。如果查看其status文件,也能發(fā)現(xiàn)相應信息。

2.統(tǒng)計系統(tǒng)性能消息

在Linux中有一些可以統(tǒng)計系統(tǒng)性能的方法,在Android中也有所支持。使用vmstat和top命令可以統(tǒng)計系統(tǒng)中性能的信息。

vmstat(Virtual Meomory Statistics,虛擬內存統(tǒng)計),命令報告關于內核線程、虛擬內存、磁盤、陷阱和CPU活動的統(tǒng)計信息。由vmstat命令生成的報告可以用于平衡系統(tǒng)負載活動。

vmstat的使用如下所示:

    # vmstat &
    # procs  memory                        system           cpu
     r  b    free mapped   anon   slab    in   cs  flt  us ni sy id wa ir
     0  0    3792  21112  50864   3724    27   66    0   1  0  1 99  0  0
     0  0    3792  21112  50864   3724    22   53    0   0  0  0 99  0  0
     0  0    3792  21112  50864   3724    28   63    0   1  0  2 98  0  0
     1  0    1752  22168  51348   3744    94  235    4  43  0 18 39  0  0
    10  1    1384  20968  52932   3760   123  555   21  60  0 38  0  2  0
    11  1    1700  19340  53424   3852   366  322    8  80  0 21  0  0  0
     5  0    1996  19748  53688   3800   150  337    5  82  0 17  0  0  0
     4  1    1320  20584  53568   3688   154  584   15  67  0 33  0  0  0
     2  1    1632  20448  53624   3500   150  422   18  66  0 33  0  1  0

vmstat的結構中幾個比較重要的值的含義如下所示。

r:在運行隊列中等待的進程數(shù)

b:在等待io的進程數(shù)

w:可以進入運行隊列但被替換的進程

free:空閑的內存(單位k)

mapped:影射的內存(單位k)

in:每秒的中斷數(shù),包括時鐘中斷

cs:每秒的環(huán)境(上下文)切換次數(shù)

us:CPU使用時間

sy:CPU系統(tǒng)使用時間

id:閑置時間

top程序主要可以檢測各個進程對CPU的消耗情況,信息將一屏一屏的階段性地打印到屏幕上。

在Android中,第1次top程序的使用如下所示:

    # top &
    User 93%, System 6%, IOW 0%, IRQ 0%
    User 309 + Nice 0 + Sys 20 + Idle 0 + IOW 0 + IRQ 0 + SIRQ 0 = 329
      PID CPU% S  #THR     VSS     RSS PCY UID      Name
      270  82% S    17 133980K  21628K  fg app_5    com.cooliris.media
      62  12% S    44 152976K  25928K  fg system   system_server
      301   3% R     1    908K    388K  fg root     top
        4   0% S     1      0K      0K  fg root     events/0
        5   0% S     1      0K      0K  fg root     khelper
        6   0% S     1      0K      0K  fg root     suspend
        7   0% S     1      0K      0K  fg root     kblockd/0
    8   0% S     1      0K      0K  fg root     cqueue
    9   0% S     1      0K      0K  fg root     kseriod
   10   0% S     1      0K      0K  fg root     kmmcd
   11   0% S     1      0K      0K  fg root     pdflush
   12   0% S     1      0K      0K  fg root     pdflush
   13   0% S     1      0K      0K  fg root     kswapd0
   14   0% S     1      0K      0K  fg root     aio/0

top使用的第2次統(tǒng)計的內容如下所示:

    User 14%, System 5%, IOW 0%, IRQ 0%
    User 47 + Nice 0 + Sys 18 + Idle 249 + IOW 0 + IRQ 0 + SIRQ 0 = 314
      PID CPU% S  #THR     VSS     RSS PCY UID      Name
      34  13% S    14  29084K   2928K  fg media    /system/bin/mediaserver
      62   3% S    44 153040K  26532K  fg system   system_server
      301   3% R     1    916K    404K  fg root     top
      125   0% S    17 119236K  16508K  fg radio    com.android.phone
      39   0% S     1    844K    336K  fg root     /system/bin/qemud
        6   0% S     1      0K      0K  fg root     suspend
        7   0% S     1      0K      0K  fg root     kblockd/0
        8   0% S     1      0K      0K  fg root     cqueue
        9   0% S     1      0K      0K  fg root     kseriod
      10   0% S     1      0K      0K  fg root     kmmcd
      11   0% S     1      0K      0K  fg root     pdflush
      12   0% S     1      0K      0K  fg root     pdflush
      13   0% S     1      0K      0K  fg root     kswapd0
      14   0% S     1      0K      0K  fg root     aio/0

以上top程序統(tǒng)計的情況是,剛剛打開Gallery(3D版本)程序,因此com.cooliris. media,也就是Gallery3D的程序,這個進程占用的CPU消耗最大,同時top程序本身也占用了一些CPU消耗。然后打開了視頻播放程序,因此,/system/bin/mediaserver進程的消耗變?yōu)樽畲蟆?/p>

Andoir中還提供了dumpstat和dumpsys兩個工具,可以用于將各個進程的stat中的信息和sys文件系統(tǒng)的內容導出。這兩個工具導出的內容都較多,最好在主機端配合adb來使用,例如:

    $ adb shell dumpstat |  grep CPU

3.內核和驅動的調試

使用dmesg可以查看內核打印出來信息,如下所示:

    # dmesg

ioctl是Android中的一個工具,用戶可以直接控制設備節(jié)點的ioctl命令,這樣可以在沒有寫程序的情況下進行一些測試工作。

ioctl的使用如下所示:

    # ioctl -h
    ioctl [-l <length>] [-a <argsize>] [-rdh] <device> <ioctlnr>
      -l <lenght>   Length of io buffer
      -a <argsize>  Size of each argument (1-8)
      -r             Open device in read only mode
      -d             Direct argument (no iobuffer)
      -h             Print help

例如,使用ioctl程序,查看framebuffer驅動的情況如下所示:

    # ioctl -l 16 -r /dev/graphics/fb0 0x4600
    sending ioctl 0x4600 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00
    return buf: 40 01 00 00 e0 01 00 00 40 01 00 00 c0 03 00 00

linux/fb.h中定義了獲取framebuffer信息的ioctl命令FBIOGET_VSCREENINFO為0x4600,如下所示:

    #define FBIOGET_VSCREENINFO     0x4600

FBIOGET_VSCREENINFO這個ioctl命令使用的結構體為struct fb_var_screeninfo,前面幾個字節(jié)的內容如下所示

    struct fb_var_screeninfo {
        __u32 xres;                   /* 可見分辨率   */
        __u32 yres;
        __u32 xres_virtual;         /* 虛擬分辨率   */
        __u32 yres_virtual;
        /* ......省略部分內容 */
    }

以上的命令使用讀取了16字節(jié)的消息,得到的信息的含義為:

    0x140==320 0x1E0==480 0x3C0==960

因此,表示屏幕的可見的寬為320,可見的高為480,虛擬的寬為320,虛擬的高為960,這就是雙緩沖的屏幕。

4.Android的特殊調試命令

在Android的toolbox中包含了一些非標準化的輔助命令,這些命令在Linux的shell中沒有,專門為Android系統(tǒng)所用。

netcfg是Android中的一個網絡工具,用于配置網絡,使用方法如下所示

    # netcfg -h
    usage: netcfg [<interface> {dhcp|up|down}]

在仿真器連接網絡的情況上查看:

    # netcfg
    lo       UP    127.0.0.1       255.0.0.0       0x00000049
    eth0     UP    10.0.2.15       255.255.255.0   0x00001043
    tunl0    DOWN  0.0.0.0         0.0.0.0         0x00000080
    gre0     DOWN  0.0.0.0         0.0.0.0         0x00000080

Service工具用于和Android一個已經啟動的Service進行通信。Service命令的使用方式如下所示:

    # service -h
    Usage: service [-h|-?]
          service list
          service check SERVICE
          service call SERVICE CODE [i32 INT | s16 STR] ...
    Options:
      i32: Write the integer INT into the send parcel.
      s16: Write the UTF-16 string STR into the send parcel.

使用service list可以顯示系統(tǒng)已經啟動的服務,如下所示:

    # service list
    Found 49 services:
    0    phone: [com.android.internal.telephony.ITelephony]
    1    iphonesubinfo: [com.android.internal.telephony.IPhoneSubInfo]
    2    simphonebook: [com.android.internal.telephony.IIccPhoneBook]
    3    isms: [com.android.internal.telephony.ISms]
    45   media.audio_policy: [android.media.IAudioPolicyService]
    46   media.camera: [android.hardware.ICameraService]
    47   media.player: [android.media.IMediaPlayerService]
    48   media.audio_flinger: [android.media.IAudioFlinger]

這里顯示的服務包括了Java層啟動的服務和C中啟動的服務。例如以上列出的內容中:phone就是Java層啟動的服務,media.player中就是C中啟動的服務。

使用service check查看服務的狀態(tài),如下所示:

    # service check media.player
    Service media.player: found

使用service call調用進程的情況如下所示:

    # service call media.player 3 s16 "file:///sdcard/a.mp4"
    Result: Parcel(
      0x00000000: 00000000 40806d54 a821a0e5 73622a85 '....Tm.@..!..*bs'
      0x00000010: 0000017f 00000000 00000000           '............    ')
    # D/MediaPlayerService(   34): Can't decode    by path, use filedescriptor instead

事實上,這種調用已經調用到了MediaPlayerService中的函數(shù),因此打印出了上述的調試信息。

am命令是在控制臺中可以非常容易調試程序的工具,例如可以啟動活動、啟動服務和發(fā)送廣播等功能。am命令的基本使用方法如下所示:

    # am
    usage: am [subcommand] [options]
        start an Activity: am start [-D] [-W] <INTENT>
            -D: enable debugging
            -W: wait for launch to complete
        start a Service: am startservice <INTENT>
        send a broadcast Intent: am broadcast <INTENT>
        start an Instrumentation: am instrument [flags] <COMPONENT>
            -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)
            -e <NAME> <VALUE>: set argument <NAME> to <VALUE>
            -p <FILE>: write profiling data to <FILE>
            -w: wait for instrumentation to finish before returning
        start profiling: am profile <PROCESS> start <FILE>
        stop profiling: am profile <PROCESS> stop

使用am start是其中的一個功能,以INTENT作為參數(shù),INTENT使用的選項如下所示:

    <INTENT> specifications include these flags:
        [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
        [-c <CATEGORY> [-c <CATEGORY>] ...]
        [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
        [--esn <EXTRA_KEY> ...]
        [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
        [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
        [-n <COMPONENT>] [-f <FLAGS>]
        [--grant-read-uri-permission] [--grant-write-uri-permission]
        [--debug-log-resolution]
        [--activity-brought-to-front] [--activity-clear-top]
        [--activity-clear-when-task-reset] [--activity-exclude-from-recents]
        [--activity-launched-from-history] [--activity-multiple-task]
        [--activity-no-animation] [--activity-no-history]
        [--activity-no-user-action] [--activity-previous-is-top]
        [--activity-reorder-to-front] [--activity-reset-task-if-needed]
        [--activity-single-top]
        [--receiver-registered-only] [--receiver-replace-pending]
        [<URI>]

使用am命令啟動計算器應用(實際是使用顯式Intent)的方式如下所示:

    # am start -n com.android.calculator2/com.android.calculator2.Calculator

使用am命顯示一幅圖片(實際是使用隱式Intent)的方式如下所示:

    # am start -a android.intent.action.VIEW -d file:///sdcard/a.jpg -t image/*

5.Logcat工具

logcat是Android中的一個命令行工具,可以用于得到程序的log信息。Logcat的使用方法如下所示:

    logcat [options] [filterspecs]

logcat工具的具體選項如表3-2所示。

表3-2 logcat工具的選項

在Android的本地代碼中,通常具有如下的設置。

    //#define LOG_NDEBUG 0
    #define LOG_TAG "XXX"
    #include <utils/Log.h>

將#define LOG_NDEBUG 0的注釋取消,即可獲得DEBUG的調試信息,而LOG_TAG表示調試信息的前綴。

主站蜘蛛池模板: 星子县| 西城区| 务川| 英德市| 广饶县| 嘉义县| 九龙坡区| 沂水县| 海原县| 方山县| 安图县| 卢湾区| 威海市| 丰城市| 翁源县| 九寨沟县| 黑山县| 依安县| 原平市| 双鸭山市| 嘉祥县| 新丰县| 东丰县| 阿拉尔市| 昌黎县| 长治县| 陆良县| 长垣县| 资兴市| 兰西县| 花垣县| 灵石县| 浦县| 饶阳县| 保山市| 永春县| 卢龙县| 桃园县| 盐亭县| 六安市| 长海县|