赞
踩
Monkey源码获取:https://android.googlesource.com/platform/development.git/
monkey,一个Android平台的命令行工具,对于你是不是既熟悉又陌生,我相信很多同学一定熟悉monkey的使用,多数都是copy命令行,哈哈,陌生的是你对它的原理可能完全不懂吧,monkey程序是如何实现的呢?让我们学习学习monkey的业务逻辑!
monkey源码下载地址:https://github.com/aosp-mirror/platform_development/tree/master/cmds/monkey
- adb shell type monkey
- monkey is a tracked alias for /system/bin/monkey
Android基于Linux内核,所以它也有内置的type命令【备注:type命令是一个可执行文件(程序),用于查看可执行文件的类型】, 当我们执行如下语句
adb shell type monkey
标准输出中则会出现这么一行:monkey is a tracked alias for /system/bin/monkey
这句话的意思是:monkey是/system/bin/monkey这个可执行文件的别称【备注:别称是类unix系统的下概念,大家可以私下去学习】,当我们输入adb shell monkey的时候,实际运行的程序为Android系统中的/system/bin/monkey这个可执行文件,接下来我们学习/system/bin/monkey这个文本文件的内容是什么呢?
- # Script to start "monkey" on the device, which has a very rudimentary
- # shell.
- #
- base=/system
- export CLASSPATH=$base/framework/monkey.jar
- trap "" HUP
- for a in "$@"; do
- echo " bash arg:" $a
- done
- exec app_process $base/bin com.android.commands.monkey.Monkey "$@"
这个代码量也不大,我就都贴上来了,下面听我慢慢道来!!!
/system/bin/monkey是monkey的可执行文件(程序),本身也是个文本文件(拥有字符编码的文本,就是文本文件),它是位于/system/bin目录下的一个shell脚本文件【备注:具备可执行权限的文本文件,遵守了bash规范,常称为shell脚本程序,简称shell脚本】
接下来分析这个shell脚本文件的详细代码内容
备注:#开头的是shell脚本编程中的注释
1、创建全局变量base,用于存储目录名称
创建一个称为base的全局变量,变量值是字符串/system,存储的是一个字符串路径(备注:shell脚本只有一种数据类型:字符串)
2、导出环境变量值,用于记录monkey.jar文件的绝对路径
export命令用于导出环境变量CLASSPATH,该环境变量值是$base/framework/monkey.jar(备注:$字符是shell编程中的变量值替换字符,shell解释器会先执行变量值替换),这里是两个步骤
第一:shell脚本解释器先做变量值替换(就是将变量名替换为变量值)
第二:再做字符串拼接(备注:shell脚本的字符串拼接,仅需紧挨着,不用+号)
由于$base会被替换为/system,所以最终的CLASSPATH的变量值为/system/framework/monkey.jar
monkey.jar是monkey项目的字节码jar包,里面都是.class字节码文件,可见monkey程序是Java写的……(are you sure?难道不是dex?),这个CLASSPATH环境变量就是给Java虚拟机程序读取用的
3、捕获HUB信号,然后处理
trap命令用于捕获信号,然后处理,HUP:HUP表示中断信号,用户键入<Ctrl+X>时由终端驱动程序发送的信号,中间""表示捕获信号之后做的事情,这里表示捕获到HUP信号后什么也没有做!【备注:信号是Linux进程间通信的方式之一】
4、循环所有命令行参数,写入标准输出(屏幕)……
一行一个的打印命令行参数(以空格字符隔开),shell中for循环的语法,echo命令用于向屏幕中输出内容,$@可以获取到所有的命令行参数,我们给monkey命令传入的所有命令行参数,echo将接收到的所有命令行参数原样写入到标准输出
5、替换程序,可执行文件(程序)app_process开始运行
exec命令用于在当前shell进程中替换一个新的程序,这里会替换一个新的程序运行,这个程序就是app_process。此处最初为shell进程,接着shell进程执行的程序替换为app_process(当前的shell程序会被替换,改为执行app_process程序的代码逻辑),$bash/bin和com.android.commands.monkey.Monkey、还有"$@"解析出来的所有命令行参数,会拼接一个一个的命令行函数再传递给app_process程序(可执行文件)
app_process是一个可执行文件,由c++编写的程序,它会创建虚拟机实例,用来执行Java程序
执行Java程序时,会将所有命令行参数,传入Java程序的入口类
Android上的一个可执行文件(程序),由c++编写,它是zygote进程中实际运行的程序,在app_process程序中会创建虚拟机实例(Android平台中的ART虚拟机),由于app_process涉及内容多,该篇点到为止,后面会专门写一篇app_process程序的分析(这个卷了,c++不熟悉),这里暂时知道monkey程序的主要业务逻辑都是在monkey.jar包中的字节码文件中,app_process程序根据约定会读取CLASSPATH环境变量的值,由于CLASSPATH环境值指向的是CLASSPATH=$base/framework/monkey.jar,所以app_process程序会从monkey.jar文件中,查找作为命令行参数的com.android.commands.monkey.Monkey类,接着加载这个Monkey类到ART虚拟机中,开始执行Java程序了。
adb shell monkey -p your.package.name -v 500
我们在命令行中执行如上一行monkey命令(程序),共计传入4个命令行参数到monkey脚本中【备注:shell编程中的空白字符用于隔开每个单词作为命令行参数】
以下是shell解释器执行完变量值替换后的monkey程序【备注:shell解释器背后会先做变量值替换,接着是命令行参数替换,最后才会执行命令】
- # Script to start "monkey" on the device, which has a very rudimentary
- # shell.
- #
- base=/system
- export CLASSPATH=/system/framework/monkey.jar
- trap "" HUP
- for a in -p your.package.name -v 500; do
- echo " bash arg:" $a
- done
- exec app_process $base/bin com.android.commands.monkey.Monkey -p your.package.name -v 500
1、com.android.commands.monkey.Monkey,该参数表示此Java程序的入口类为Monkey,按照java程序的规范(标准),Monkey类的静态方法main()会执行,而Monkey类后面的所有命令行参数,比如上文中提及的传入的几个参数,会全部传递到Java程序中(app_process程序调用Java程序时执行的)
2、在我的第二篇文章中,我将分析Java程序Monkey类的静态方法main(),静态方法main()是monkey程序的入口,monkey的主线程流程(进程)将在此运行
3、Android平台的monkey程序,涉及到shell脚本程序(monkey)、c++程序(app_process)、java程序,主要的业务逻辑全部在Java程序中,佩服佩服,牛逼牛逼!!!!程序之间相互调用,简直太拽了…………
4、本人不会c++程序,有点遗憾啊,什么时候恶补一波啊,不然总觉得缺点什么!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。