android binder机制 简析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/alcoholdi/article/details/53998869

学安卓Binder应该是必须了解的东西。花了几天时间阅读Google前3页的binder文章。

其中主要阅读了Gityuan的Binder系列文章http://gityuan.com/2015/10/31/binder-prepare/

很给力,一看还是我大小米的系统工程师,膜拜膜拜。




Binder是什么?

Binder是Android的一个类,继承IBinder接口

Binder是一种进程间通信方法,因为种种优点被Android大量使用

Binder可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder


为什么Android要使用Binder,尤其是在Linux拥有好几个传统进程间通信方法的情况下还要开发出Binder?

这个问题就是等于问Linux传统进程间通信方法有什么缺点,然后Binder怎么把缺点补齐的。

先列下传统方法。有管道、消息队列、共享内存、socket、信号量

然后分几方面讲

1.性能角度

Binder数据拷贝只需要拷贝一次(Service端拷贝到内核,Client端是则是获取内核中Binder引用,无需拷贝直接使用)。

而管道、消息队列、socket都需要2次。共享内存无需拷贝,但是操作复杂,需要考虑并发问题。

2.稳定性和架构设计角度

Binder基于Client-Service架构设计,降低耦合,相对独立,稳定性好,方便android程序之间相互通信。

共享内存这种就没有C/S区分。

3.安全性角度

传统的进程间通信不需要报出自己的身份,或者自己的身份自己填写。这样的方式放在android上肯定是不合适的。

意味着随意一个进程都可以要随意访问或者伪造身份访问联系人,短信,通话记录。

所以android开发的Binder机制,设计成Binder强制为进程填写UID/PID,并且在Binder通信时会根据UID/PID进行有效性检测。这样就约束了每个进程对权限的使用。


Servicemanager是干什么的

ServiceManager也是一个Service端,只不过它的作用是Service端的管家。

很容易理解,如果只有Service和Client,如果client要找到某个Service,是很费力的。所以需要一个服务管理者的角色存在。

Android系统中需要公开的服务,在完成创建后,都将把自己注册到ServiceManager里面。相当于路由表。

后面的Client想要访问某个服务功能,就需要先到ServiceManager中查找和获取。

那么问题来了,Server向ServerManager注册时,也算是进程间通信,当时没有“这个路由表”,怎么实现的。

答案是ServiceManager作为用户控件的一个守护进程,启动时会告诉Binder驱动它是服务管理者。

Binder驱动会新建ServiceManager对应的Binder对象,并将Binder实体设为全局变量。

其他文章有讲,ServiceManager被赋予一个特殊的句柄——0句柄。其他Service进程通过0句柄与ServiceManager通信。



Server向ServiceManager注册的细节

1.首先,XXXServer(XXX代表某个)在自己的进程中向Binder驱动申请创建一个XXXService的Binder的实体,
2.Binder驱动为这个XXXService创建位于内核中的Binder实体节点以及Binder的引用,注意,是将名字和新建的引用打包传递给SM(实体没有传给SM),通知SM注册一个名叫XXX的Service。
3.SM收到数据包后,从中取出XXXService名字和引用,填入一张查找表中。


Client获取远程服务细节

Client发送请求(服务名)到Binder驱动, Binder驱动转发给ServiceManager进程

ServiceManager也是通过Binder驱动把 Server对应的Binder实体的Binder引用信息(XXXBpBinder)反馈给Client

Client收到之后,创建出一个Server对应的远程服务,这个远程服务就是Server的代理.

所以通信流向大概是Client —— Server远程服务的接口 —— Binder驱动 —— Server


关于Binder实体和Binder引用

Binder实体 : 是各个Server以及ServiceManager在内核(Binder驱动)中的存在形式
Binder引用 : 是Client在内核(Binder驱动)中保存的一个Binder实体的引用
一个Binder实体 可以对应  多个Binder引用


关于IBinder接口和Binder类

Binder 类实现 IBinder 接口。IBinder 有个关键方法 transact(),是客服端向服务端发出调用(方法)请求。当然这个抽象的,具体实现还是在Binder里面。

Binder 有个关键方法 onTransact(),是服务端接收客服端的请求,作出响应并返回。

这一系列操作是同步的,所以代码中 transact() 方法里执行 onTransact(),会等待 onTransact() 执行完成,返回后者的执行结果。

onTransact 接收目标方法ID、方法参数、返回结果,最终会分发到真正执行业务的目标方法中。

    public final boolean transact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);
        if (data != null) {
            data.setDataPosition(0);
        }
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
    }






猜你喜欢

转载自blog.csdn.net/alcoholdi/article/details/53998869