Android系统级开发--基于NDK的so库及bionic库(未完)

这部分主要涉及到dalvik虚拟机,自己编写的jni及so库,系统的Bionic库,系统的External软件。

一. dalvik虚拟机单步调试

1. 首先编译好dalvik 

2. 在用gdb启动dalvik时,创建了一个脚本来进行环境配置,脚本名grund.sh,放于Android源码根目录。下面为脚本内容:注意必须包含下述几个jar包: core ext dexopt framework android.policy services   编译后可能会在target那个目录下,复制过去即可
#!/bin/sh
base='/home/czwcarelife/code'                    //自己根据本地目录设定
root=$base/out/host/linux-x86                  //不同得android源码,编译时候方法不同,导致这个可能也需要改变
export ANDROID_ROOT=$root
bootpath=$root/famework
export BOOTCLASSPATH=$bootpath/core.jar:$bootpath/ext.jar:$bootpath/framework.jar:$bootpath/android.police.jar
export ANDROID_DATA=/tmp/dalvik_test
mkdir -p $ANDROID_DATA/dalvik-cache
exec gdb $root/bin/dalvikvm                //同第二点

  1. 3.开始调试
  2. 准备一个hello.java,编译后将hello.jar拷贝至Android 源码根目录。
  3. 进入到Android 源码根目录
  4. 执行 ./grund.sh 
  5. gdb提示符后输入 “set args –cp hello.jar hello”
  6. 此时可以单步调试dalvik了,比如在main.c 212行设置断点(输入 “b 212”
  7. 之后就是gdb的事了。。。

4.附hello.java   的 makefile
ANDROID_SRC_DIR := /home/czwcarelife/code
android_dir_dx = $(ANDROID_SRC_DIR)/out/host/linux-x86/bin/dx

all:
        javac hello.java
        $(android_dir_dx) --dex --output=hello.jar hello.class

clean:
        @rm *.jar *.class      

二. android ndk使用及c层代码的单步调试


1、下载ndk-r4
官方的下载地址当然是:developer.android.com/sdk/ndk/index.html啦,不过由于和谐的原因我们下载不了。可以通过代理的方式去下载,相信大家总会有办法下载下来的。

2、安装ndk-r4
其实很简单了,只用一个命令就行:
$unzip android-ndk-r4-linux-x86.zip
解压完毕后会看到一个叫做android-ndk-r4的目录,这个目录需要export到当前的PATH环境变量里面去:
$export PATH=~/android-ndk-r4:$PATH
然后这个ndk就安装好了。(不要问我怎么不运行build/host-setup.sh脚本,那东西已经在r4被淘汰掉了)

3、编译个hello world看看
$cd ~/android-ndk-r4/samples/hello-jni/
$ndk-build
Gdbserver      : [arm-eabi-4.4.0] /home/wayne/android-ndk-r4/samples/hello-jni/libs/armeabi/gdbserver
Gdbsetup       : /home/wayne/android-ndk-r4/samples/hello-jni/libs/armeabi/gdb.setup
Gdbsetup       : + source directory /home/wayne/android-ndk-r4/samples/hello-jni/jni
Install        : libhello-jni.so => /home/wayne/android-ndk-r4/samples/hello-jni/libs/armeabi
如果看到上面的输出,呵呵,恭喜恭喜,jni的so库已经编译成功了。

4、生成一个apk看看吧
这一步比较烦,要求必须安装了ant以及最新的android sdk,并且把$ANDROID_SDK/tools和ant的bin目录也export到PATH环境变量里面才行。
在此偶只贴出来偶的配置:
$export PATH=/usr/local/apache-ant-1.8.1/bin:$PATH
$export PATH=/home/wayne/android-sdk-linux_86/tools:$PATH
当然了,这些对PATH的修改,可以直接写到/etc/profile文件中,下次一进入shell就会自动准备好,在此按下不表。

好了,开始生成apk
$cd ../
$android update project --path hello-jni
$cd hello-jni
$ant debug
Buildfile: /home/wayne/android-ndk-r4/samples/hello-jni/build.xml
    [setup] Android SDK Tools Revision 6
    [setup] Project Target: Android 2.2
    [setup] API level: 8
    [setup] WARNING: Attribute minSdkVersion in AndroidManifest.xml (3) is lower than the project target API level (8)
    [setup] Importing rules file: platforms/android-8/ant/ant_rules_r2.xml

-compile-tested-if-test:

-dirs:
     [echo] Creating output directories if needed...

-resource-src:
     [echo] Generating R.java / Manifest.java from the resources...

-aidl:
     [echo] Compiling aidl files into Java classes...

compile:
    [javac] /home/wayne/android-sdk-linux_86/platforms/android-8/ant/ant_rules_r2.xml:255: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 1 source file to /home/wayne/android-ndk-r4/samples/hello-jni/bin/classes

-dex:
     [echo] Converting compiled files and external libraries into /home/wayne/android-ndk-r4/samples/hello-jni/bin/classes.dex...

-package-resources:
     [echo] Packaging resources
 [aaptexec] Creating full resource package...

-package-debug-sign:
[apkbuilder] Creating HelloJni-debug-unaligned.apk and signing it with a debug key...
[apkbuilder] Using keystore: /home/wayne/.android/debug.keystore

debug:
     [echo] Running zip align on final apk...
     [echo] Debug Package: /home/wayne/android-ndk-r4/samples/hello-jni/bin/HelloJni-debug.apk

BUILD SUCCESSFUL
Total time: 7 seconds
这些命令运行完毕后,如果看到上面的输出,代表生成的apk是正常的,然后就是安装程序。

5、安装和调试程序
偶是android的fans,因此,nexus one早早就刷了froyo 2.2,因此直接在手机上装了。鉴于很多朋友没有nexus one,偶在下面还是用emulator做演示比较好。

首先,运行android命令,新建一个2.2的emulator。(建立模拟器的方法不再聒噪,如下图所示)

其次,进入android-ndk-r4/samples/hello-jni/bin目录,应该能够找到一个apk安装包,直接安装即可。
$adb install ./HelloJni-debug.apk
1201 KB/s (78926 bytes in 0.064s)
        pkg: /data/local/tmp/HelloJni-debug.apk
Success
看到Success,就代表已经安装成功了。

然后,注意,忍受了偶上面那么多废话的朋友们,下面就是关键的地方了!
$cd ~/android-ndk-r4/samples/hello-jni/
$ndk-gdb
此时,观察模拟器的反应,hoho,是不是看到模拟器里面的hello-jni程序自己打开了?!

然后就是ndk-gdb自动进入了一个命令行提示符的状态:
and track explicitly loaded dynamic code.
warning: shared library handler failed to enable breakpoint
0xafd0eb08 in ?? ()
(gdb) list
1      
17      #include
18      #include
19      #include
20
(gdb) list
21      static void upper_str(char *s, int len) {
22        int i ; 
23        for(i = 0 ; i < len ; i++) {
24          if((s[i] >='a') && (s[i] <='z')) {
25            s[i] = s[i] - 'a' + 'A' ; 
26          }
27        }
28      }
29
30      /* This is a trivial JNI example where we use a native method
(gdb)
在linux做过开发的朋友们一定对gdb的命令行模式非常熟悉吧?到这里就一切豁然开朗了。

可能有朋友要问,怎么有一大堆的warning,好象是说什么符号找不到?
其实这很简单,android 2.2版本的模拟器自然是release版啦,debug版的一定慢得要死,所以,很多函数的库和符号是没有的,因此,在gdb里面根本找不到也是有情可原的,只要忽略掉这些就行了(偶是多么容易满足的人啊!在此赞叹一下。另外插一句,如果有人真的爱钻牛角尖,要弄清楚这个的话,可以尝试用android的源代码编译一个debug版的android,偶试过的可以调试native的程序,而且也没有这些warning,不过又会是一个痛苦的过程)。

然后就是常规的gdb调试命令了。
list-显示代码
x-查看内存
p-查看变量
b-设置断点
cont-程序继续运行
s-单步执行,但可以跟踪进入函数
n-单步执行,但不会进入函数
吧啦吧啦吧啦,关于gdb的使用,偶就不再聒噪了,网上相关说明非常多。

这里需要提醒一下,相信细心的朋友已经看到怎么偶的界面跟大家的hello-jni不一样?!

android的在线调试的基本原理并不是本地的gdb程序,而是在模拟器(或者真机)上启动了一个叫做gdb-server的东西,通过adb的tcp中转,让开发者本机的gdb与模拟器(或者真机)上的gdb-server进行连接,然后进行调试。这个过程相对比较繁琐,感兴趣的朋友可以参考ndk-gdb这个脚本(hoho,想当年偶调试native程序的时候,是自己写的连接gdb和gdb-server的脚本,期间问候了无数次google的祖宗多辈,在此按下不表)

在hello-jni里面,jni函数的调用是放在activity的oncreate函数中的,也就是说一程序一启动就已经调用了jni,而在pc端的gdb联上模拟器的gdb-server的时候,jni已经运行完了,而且oncreate函数也不是随便说调用就调用的,因此,在什么地方下断点呢?!偶就想了个土法,那就是修改一下原有的hello-jni程序,在里面添加一个小button,按下这个button的时候才会调用jni的函数。

如此一来,使用ndk-gdb的时候只是启动了activity,并不会真的调用jni函数,当偶把函数的断点都设置好以后,再运行“cont”命令,然后单击一下按钮,这个时候才会真的跑到断点里面来。


你可能感兴趣的:(Android,系统级开发)