[android framework开发]Android开发的IPC主板模式设计

更新时间:2020-03-14    来源:.Net开发    手机版     字体:

【www.bbyears.com--.Net开发】

一、认识Android的IPC主板模式


系统架构设计最关键的任务就是组合(或称整合),而且最好是能与众不同、深具创新性组合。Android就擅用了主板模式,以通用性接口实践跨进程的IPC通信机制。由于Android是开源开放的系统,其源代码可成为大家观摩的范本。首先,其主板模式提供了IBinder通用性接口。如下图:


技术分享

Android定义一个Binder父类来实现<通用性>的IBinder接口。如下图:


技术分享

然后,以Java来撰写这个实现类,其Java代码如下:

// Android的源代码
// Binder.java
// -------------------------------------------------------------
public class Binder implements IBinder {
    // ..........
    private int mObject;
    public Binder() {
        init();
        // 其它代码
    }
   public final boolean transact(int code, Parcel data, Parcel reply,  int flags)
                throws RemoteException {
                // 其它代码
                boolean r = onTransact(code, data, reply, flags);
                return r;
    }
private boolean execTransact(int code, int dataObj, int replyObj, int flags) {
        Parcel data = Parcel.obtain(dataObj);
        Parcel reply = Parcel.obtain(replyObj);       
        boolean res;
        res = onTransact(code, data, reply, flags);
        // 其它代码
        return res;
    }
   protected boolean onTransact(int code, Parcel data, Parcel reply,  int flags) 
                     throws RemoteException {
        }
   private native final void init();
}
// End

这个Binder抽象父类的主要函数:

transact()函数-- 用来实作IBinder的transact()函数接口。

execTransact()函数-- 其角色与transact()函数是相同的,只是这是用来让C/C++本地程序来调用的。

onTransact()函数-- 这是一个抽象函数,让应用子类来覆写(Override)的。上述的transact()和execTransact()两者都是调用onTransact()函数来实现反向调用(IoC, Inversion of Control)的。

init()函数-- 这是一个本地(Native)函数,让JNI模块来实现这个函数。Binder()构造函数(Constructor)会调用这个init()本地函数。

这Binder.java是抽象类,它含有一个抽象)函数:onTransact()。于是,这个软件主板提供了两个接口:CI和接口。如下图:


技术分享

这是标准型的主板模式。此图里的Binder抽象父类和两个接口,整合起来成为一个典型的软件主板。如下图:


技术分享

这个Binder软件主板是用来整合两个进程里的软件模块(如类),所以我们称之为:。如下图:


技术分享

基于这个主板,我们就能开始进行组合了。此时,可设计一个子类,并且装配到主板的接口上。如下图:


技术分享

图 1 Binder进程间通信模型

Client和Server均通过函数ioctl与Binder驱动进行数据交互。ioctl是Linux中用于控制I/O设备的函数,提供了一种同时向设备发送控制参数和数据的手段。它是一个可变参数的函数,原型为:

<??#65533;"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHByZSBjbGFzcz0="brush:java;">int ioctl(int fd, int cmd, ...);

fd是打开/dev/binder设备后得到的文件描述符,cmd是对设备的控制命令。该函数执行成功返回0,否则返回-1。

3.相关数据结构

当函数ioctl的第二个参数cmd为BINDER_WRITE_READ时,表示向Binder驱动发送一条读取或者写入/dev/binder设备的命令,Binder驱动会将对设备的读写“翻译”为对共享

内存区的读写。这条命令是Client和Server进行进程间通信时最重要、使用最频繁的控制命令。

传入BINDER_WRITE_READ的同时,会传入一个binder_write_read结构体的指针作为ioctl的第三个参数,该结构中的read_buffer和write_buffer字段分别指向将要读取或者写入的缓冲区。这两个缓冲区中的数据都是以“数据类型+数据内容”的格式顺序存放的,而且多条不同类型的数据连续存放,如图2所示。write_buffer中数据类型以“BC_”开头,而read_buffer中数据类型以 “BR_”开头,图2中以write_buffer中的数据为例。在所有的数据类型中,又以BC(R)_REPLY和BC(R)_TRANSACTION 最为重要:通过BC_TRANSACTION/BC_REPLY这对命令,发送方将数据发往接受方;通过BR_TRANSACTION /BR_REPLY,接收方读取发送方发来的数据。

数据的内容是一个binder_transaction_data结构。


\

图2 Binder IPC中各数据结构的关系

binder_transaction_data结构是对进程间通信数据的封装,可以看作网络通信中的一个数据包。其中的 sender_uid,sender_pid成员变量指明了此数据发送方的用户ID和进程ID,buffer成员变量指向进程间通信最核心的有效负载数据,data_size是有效负载数据的长度。在Binder机制中,sender_uid和sender_pid是在内核中由Binder驱动填入的,无法被伪造,保证了身份标记的可靠性,由此可见Binder进程间通信机制进行是安全的。

4.Binder之间的数据行为关系

Client和Server使用Binder机制进行进程间通信时,通过分析Client发往Server的数据或者分析Server读取的Client的请求数据,便可以识别出Client的具体行为。

例如,当Client想要得到定位信息,请求LocationServer获取定位数据时,会访问LocationServer的ILocationManager接口,发往LocationServer中的有效负载数

据中包含“android.location.ILocationManager”字符串。所以我们分析LocationServer读取的Client发来的请求数据,判断其中是否包含“android.location.ILocationManager”,

我们就可以知道Client是否正在试图访问用户的地理位置信息。

由于Android系统中每个应用程序都有自己唯一的UID,因此根据binder_transaction_data中的sender_uid,我们就可以获取Client具体代表的应用程序。这样

就获得了具体软件的具体行为。

通过对Android系统的分析,我们发现:虽然系统提供的服务多达几十种,但是实际上只有三个Server进程负责管理


Android系统Server进程与管理的服务


服务进程        管理的服务

com.android.phone      与通信功能相关的短信、电话服务

mediaserver     与媒体功能相关的视频、音频服务

system_server      其他服务,如地理位置、蓝牙、网络连接、程序安装卸载等


本文来源:http://www.bbyears.com/asp/87065.html

热门标签

更多>>

本类排行