如竹 2012-05-08
http://blog.csdn.net/luoshengyang/article/details/6642463
下面讲述下Android虚拟机的组成部分和一些构造原理,在介绍Android虚拟机之前,先要了解下什么是Android操作系统,所谓的Android:是基于Linux内核的软件平台和操作系统,早期由Google开发,后由开放手机联盟OpenHandsetAlliance)开发。
Linux系统中进程间通信的方式有:socket,namedpipe,messagequeque,signal,sharememory。Java系统中的进程间通信方式有socket,namedpipe等。android应用程序理所当然可以应用JAVA的IPC机制实现进程间的通信,
取而代之的是Binder通信。Google为什么要采用这种方式呢,这取决于Binder通信方式的高效率。Binder通信是通过linux的binderdriver来实现的。Binder通信操作类似线程迁移(threadmigration),两个进程间IPC看起来就象是一个进程进入另一个进程执行代码然后带着执行的结果返回。
Binder的用户空间为每一个进程维护着一个可用的线程池,线程池用于处理到来的IPC以及执行进程本地消息,Binder通信是同步而不是异步。Android中的Binder通信是基于Service与Client的,所有需要IBinder通信的进程都必须创建一个IBinder接口。
系统中有一个进程管理所有的systemservice,Android虚拟机不允许用户添加非授权的Systemservice,当然现在源码开发了,我们可以修改一些代码来实现添加底层systemService的目的。
对用户程序来说,我们也要创建server,或者Service用于进程间通信,这里有一ActivityManagerService管理JAVA应用层所有的service创建与连接(connect)。disconnect,所有的Activity也是通过这个service来启动,加载的。ActivityManagerService也是加载在SystemsServcie中的。
Android虚拟机启动之前系统会先启动serviceManager进程,serviceManager打开binder驱动,并通知binderkernel驱动程序这个进程将作为SystemServiceManager。然后该进程将进入一个循环,等待处理来自其他进程的数据。用户创建一个Systemservice后,通过defaultServiceManager得到一个远程ServiceManager的接口。
通过这个接口我们可以调用addService函数将Systemservice添加到ServiceManager进程中,然后client可以通过getService获取到需要连接的目的Service的IBinder对象。这个IBinder是Service的BBinder在binderkernel的一个参考,所以serviceIBinder在binderkernel中不会存在相同的两个IBinder对象。
每一个Client进程同样需要打开Binder驱动程序。对用户程序而言,我们获得这个对象就可以通过binderkernel访问service对象中的方法。Client与Service在不同的进程中,通过这种方式实现了类似线程间的迁移的通信方式,对用户程序而言当调用Service返回的IBinder接口后,访问Service中的方法就如同调用自己的函数。
实现接口时有几个原则:
抛出的异常不要返回给调用者.跨进程抛异常处理是不可取的。IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。
也就是IPC调用会挂起应用程序导致界面失去响应.这种情况应该考虑单起一个线程来处理,能在AIDL接口中声明静态属性。IPC的调用步骤:
1.声明一个接口类型的变量,该接口类型在.aidl文件中定义。
2.实现ServiceConnection。
3.调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.
4.在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service).调用YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换YourInterface类型。
5.调用接口中定义的方法。你总要检测到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。
6.断开连接,调用接口实例中的ApplicationContext.unbindService()