Android binder简介

来源:互联网 发布:notepad整理代码js 编辑:程序博客网 时间:2024/06/01 08:40

原文地址https://www.nds.rub.de/media/attachments/files/2011/10/main.pdf


4 Binder

本章介绍什么是Binder以及Binder的能力。本章是从抽象的角度介绍Binder,并没有涉及到实现细节,在下一章我们会讲解实现细节。

4.1 出身

Binder最初是Be Inc公司开发的OpenBinder,后来Palm Inc收购了Be Inc,这个项目随之转到了Pam公司下。主开发人员是Dianne Hackborn。在OpenBinder的文档中声称:Openbinder是一个系统级的架构,为传统的现代操作系统服务提供一个丰富的高级抽象。

更准确的说,Binder提供了对不同执行环境的粘合能力。OpenBInder实现运行在LInux之上,扩展了现在的IPC机制。OpenBinder文档中还声称:OpenBinder已经能移植到多种平台,包括BeOS, Windows,已经PalmOS Cobalt

Android上的Binder是OpenBinder的定制。在Android's M3 release 原生的kernel包含了OpenBinder的驱动部分,但是Binder的用户空间部分和OpenBinder相比被重写了,以避免OpenBinder的License和Android's的License不相容的情况。在Android's M5 release中,驱动部分也被重写了。尽管核心概念没有改变,但是很多实现细节都改变了。

原始的OpenBinder代码不再开发了。但是从某种程度上说,Android binder可以看作是OpenBinder的一个分支,被Android开发者维护着。


4.2 Binder术语

Binder framework使用它自己的数目来命名它的功能和组件。这一节介绍几个最重要的属于,细节部分会在后面讨论。

Binder 这个术语的使用一直比较模糊,有时指整个Binder框架,有时指一个Binder接口的特定实现。

Binder Object 是一个实现Binder接口的类实例。一个Binder对象可以实现多个Binders

Binder Protocol Binder中间件使用了一个非常低级的协议,用来和Binder kernel driver通信。

IBinder interface 一个Binder interface是Binder可以实现的一组定义良好的方法,属性和事件。通常使用AIDL语言描述。

Binder Token 可以用来惟一标始一个Binder的数字。


4.3 设施

Binder framework 提供了一个简单的进程间通信系统,

从Android应用开发者的角度,最重要的改变就是可以想调用本地对象方法一样,调用远程对象方法。这是一个同步方法调用。相应的,client进程在服务器给出应答之前保持block状态。这样做的好处是避免异步调用导致client要提供一个线程方法。

AIDL的一个特色就是,在高的的层次,应用不需要知道服务试运行在一个server进程还是就在进程内部。Android's的应用概念使得在进程内还是Activity进程运行服务称为可能,这使得应用开发者可以很容易的把自己的服务export给其他的Android应用。

Android系统服务使用Binder的一个特定的通知功能,称为link to death机制。这个机制允许一个进程 获得给定进程的binder结束通知。特别是这个方法允许Android window manager建立一个link to death关联到每一个window的Binder接口,使得window被关闭时通知windwo manager。

每一个Binder是唯一标始的,这意味着它可以用做共享令牌。我们假定Binder没有通过Service Manager发布,BInder标始仅仅被通讯参与者知悉,包括远程进程和本地进程。相应的一个Binder可以被看作一个安全访问令牌。令牌可以被多个进程共享。

另外一个安全特色是:被调用进程可以通过UID和PID来标始调用进程。结合Andoird的安全模型,一个进程可以被标始。另外一个特色,是共享内存机制,通过Binder framework可以共享heap

总的来说,Binder框架的特色使得它良好的支持面向对象的进程间通信。

4.4 概念

本节描述这些设施后面的概念,由于Binder缺乏公开的文档,所以本节大部分都是基于阅读代码后的理解。

4.4.1 Communication Model

Binder framework通信是client/server模型。一个client发起通信并等待Server的响应。Client端使用一个client-side proxy来进行通信。在服务器端,一个线程池来满足client发送来的请求。在图4.2中,client端进程A包括一个proxy对象,实现和Binder kernel driver的通信。Process B是一个服务器端进程,包含多个Binder线程。Binder framework创建新的线程处理所有进入的请求,直到最大允许线程数。代理对象和Binder driver通信,Bind driver负责把消息转发给目标对象。


4.4.2 Transactions

如果一个进程发送数据给其他的进程,那么称为transaction。伴随着每一次传输payload数据被提交。这些数据称为transaction data。

数据结构如图4.3。它包含一个target成员,也就是目标binder node;cookie成员用来内部信息;sender ID成员包含安全相关的信息;data成员包含一组数据,每个数组项包含一个命令和命令参数,Binber会解析这个数组。在Binder framework之上的application可以用这些参数定义它们自己的命令。在Android源代码中我们可以看到,开发者使用target command成员作为远程服务的函数指针,并且把函数的参数序列化到argument成员中。就是实现了一个用户自定义IPC协议。Binder通信依赖于request和reply机制。这就意味着每一个请求比去于一个应答,而请求进程则必须要等待应答,在等待的过程中,请求进程处于阻塞状态。如果开发者想要实现异步的IPC协议,当然是可行的,但是需要开发者注意Binder本身并不支持异步IPC,开发者必须自己实现一个机制来管理请求应答。


因此一个transaction意味着需要两条message,transaction请求和transaction reply。特例是one way通信,一路通信仅限于death notification这种功能。

4.4.3 Parcels和Marshaling

从对象的观点来说,transaction data被称为parcel。换句话说,传输的是数据结构。任何能够传输到远端的对象,都要必须实现parcelable接口。一个实现parcelable接口的对象必须提供序如下方法,在sender端能够序列化对象数据结构,并且在接收端恢复为对象数据结构。数据结构的所有成员都被简化为简单的数据类型如Int, Float,Boolean和String,然后被序列化到一个parcel中。

创建parcel的过程称为marshaling或者对象平面化,相反,从parcel重建object的过程称为unmarshaling或者去平面化

Binder的内存共享基础设施不能被JAVA 应用使用,仅仅C++库可以访问内存中的共享对象表示。


4.4.4 Death Notification

Binder framework支持Binder object的死亡通知,这是一种观察者模式。一个本地BInder 对象如果想知道一个远程Binder对象的终结,那么就把它加到观察着列表中。如果一个发生的事件是远程Binder对象销毁,那么本地对象就会得到通知执行相应的动作。图4.4演示了这一过程


4.5 Context Manager

Context manager是Binder framework中的一个特别Binder node。他对应的Binder号是0。它是一个name system,这样就可以使用一个名称来表示一个Binder接口。这非常重要,因为Clients一般不会预先知道远程Binder的地址。如果一个client预先知道了remote binder的地址,那么Binder的安全令牌机制就不能工作了。但是如果不知道远程通信伙伴的地址,那么就无法发起通信。而context manager解决了这个问题,接口地址固定并且地址是知名的。Context manager实现是Binder framework的一部分。在Android中,context manager被称为Service manager。每一个需要提供服务的Binder都要提交他的名字和Binder令牌给Server manager。而对于client端来说,仅仅需要知道服务的名字,通过名称从service manager查询所要使用服务的Binder address。


4.6 Intents

intent也就是message,开发者在Java API这一层使用它,并通过IPC发送。它是一个要执行动作的抽象表示。抽象意味着动作的执行者并没有定义在intent中。Intent仅仅包含action和data。如4.5给出来一个intent的例子。这个intent由Binder的intent reference monitor分发。service将负责执行拨号动作,所拨拨号码就是保存在Data中

有两种形式的intents,显示的intent是指一个特定的组件。另一方面,一个隐式的intent把决定权交给Android系统。如果系统有多个部件可以处理它,那么Android 系统会选择最合适的组件运行这个intent


4.7 系统集成

Binder在Android平台上使用的相当多,无论什么时候两个进程需要通信, Binder都会介入。比如window manager通过Binder framework和它的clients交换数据。同时使用Binder的death notification功能来获得client应用的结束信息。

s所以Binder连接Android系统的各个框架,因此是非常重要的一个模块。

4.8 安全模型

Binder安全模型非常简单但是很有效。它确保进程间通信通道的安全,保证通信方的身份识别。

伴随Intent的另外一个功能是intent filter。Service和app可以声明,告诉系统哪些intents可以转发给他们执行。


5. Implementation of the Binder Framework

本章会大概分析Binder framework的实现。对于每一层,源代码文件在[10] [9]中列出来,我们讨论他们的目的。此外还有AIDL,因为它被用来生成Java code,所以也可以看作是Binder framework的一部分。

图5.1演示了Binder framework的不同层次。它有三层组成。第一层也就是最高一层是Android应用API。第二层Binder framework中间件层;第三层也就是最底层则是kernel driver


5.1 AIDL

Android interface definition language AIDL是Eclipse SDK的一部分,由Google提供。它的主要目的是简化Android 远程服务的实现。AIDL使用类Java的语法。

在AIDL文件中,开发者用远程服务的方法签名定义接口。AIDL 解析器可以从接口生成Java class,首先为client 生成访问service的代理类,其次为service实现生成一个stub类,service可以扩展这个类做为远程方法的实现。

AIDL语言支持基本数据类型。它生成的代码可以实现:写值到parcels,通过Binder IPC发送 parcels,接收parcel,读取这些值,调用服务的方法,并且发送执行结果。

AIDL文件必须由远程service/app开发者和client app开发者共享。因为AIDL生成器为client和service生成的代码保存在一个文件中,每一个应用使用和实例化的仅仅是这些生成类的一个子集。

5.2 Java API Wrapper

本节讨论Java framework,这个框架位于middleware和kernel driver之上。这些source classes和interfaces属于Java API层:

Interfaces:

• android.app.IActivityManager
• android.os.Parcable
• andorid.os.IBinder
• android.content.ServiceConnection

Classes:

• android.app.ActivityManagerNative
• android.app.ContextImpl
• android.content.Intent
• android.content.ComponentName
• android.os.Parcel
• android.os.Bundle
• android.os.Binder
• android.os.BinderProxy
• com.android.internal.os.BinderInternal

Binder framework的Java layer有两个功能。一个功能是对下层中间件的封装,使得Android应用可以参与到Binder通信当中。第二个功能,它在Binder framework中引入了intents功能。

5.2.1 JNI wrapper

Java API Layer依赖于Binder中间件。为了从Java使用C++编写的中间件,必须使用JNI。在源代码文件frameworks/base/core/jni/android_util_Binder.cpp中,实现了Java和C++函数之间的映射。

5.3 C++中间件

Binder framework在用户空间的中间件实现是C++编写的。framework提供了进程和线程控制方法以及 孵化和管理新线程所需要的数据结构。Marshalling和Unmarshalling功能也是在这里实现的,所以对象信息可以在这里转换为可提交的parcel数据。中间件提供了和Binder kernel驱动的交互以及共享内存的实现。

使用C++的Services或者apps可以直接使用Binder framework,但是必须放弃Java API提供的那些功能。

源代码保存在这些文件中:

• frameworks/base/include/utils/IInterface.h
• frameworks/base/include/utils/Binder.h
• frameworks/base/include/utils/BpBinder.h
• frameworks/base/include/utils/IBinder.h
• frameworks/base/include/utils/Parcel.h
• frameworks/base/include/utils/IPCThreadState.h
• frameworks/base/include/utils/ProcessState.h
• frameworks/base/libs/utils/Binder.cpp
• frameworks/base/libs/utils/BpBinder.cpp
• frameworks/base/libs/utils/IInterface.cpp
• frameworks/base/libs/utils/ProcessSTate.cpp
• frameworks/base/libs/utils/IPCThreadState.cpp

5.4 C kernel driver

Binder kernel driver是Binder framework的核心。在这个点上,信息的可靠性和安全交付必须得到满足。kernel driver是一个使用C语言实现的内核模块。驱动代码包含下面的源文件

• /drivers/staging/android/binder.c
• /drivers/staging/android/binder.h

Binder kernel驱动支持下面的文件操作open, mmap, release, poll和系统调用ioctl。这个操作代表着上层访问Binder驱动的接口。Binder操作open建立到Binder的连接并且把这个连接赋给file pointer,而release操作则关闭连接。mmap操作是用来映射Binder内存的。ioctl是最主要的操作,上层通过这个接口提交和接收信息。ioctl操作使用Binder driver命令码和data buffer作为参数,这些命令包括:

BINDER _WRITE_READ 是最重要的命令,它提交一串transmission data。这个数据传报含多个数据,如图4.3描述的。

BINDER_SET_MAX_THREADS 设置每个进程服务请求的最大线程数。

BINDER_SET_CONTEXT_MGR 设置context manager。context manager仅存在一个,所以这个调用只能成功一次

BINDER_THREAD_EXIT 这个命令被中间件发送,如果一个binder线程退出。

BINDER_VERSION 返回Binder的版本号


Binder驱动实现的功能将在下一节讨论。这些节使用的命令是target commands。甚至如果名字是target command,这些命令可能仅仅应用到本地binder。在OpenBinder文档中他们被称为Binder driver protocol。下面要讨论的代码使用BC_前缀表示Binder command,使用BR前缀表示Binder return

5.4.1 Binder thread support

因为kernel driver没有实现thread启动机制,它必须知道多少threads启动了。下面这些命令必须发送给Binder driver,以便Binder driver能够精确的知道looping threads数目。这些Target commands是BC_REGISTER_LOOPER, BC_ENTER_LOOPER和BC_EXIT_LOOPER。这些命令是用来进行记账的。

5.4.2 Binder Transactions

命令BC_TRANSACTION和BC_REPLY命令传输数据到其他的Binder接口。BC_REPLY命令被中间件用来回答一个接收到的RC_TRANSACTION。图5.3演示了当一个Binder发送一个 transaction然后等待接收这个transaction reply过程中,和Binder driver的交互过程。


Binder驱动负责把reply提交给等待线程,可以把这个reply看作直接响应。

Binder驱动从发送进程的用户空间拷贝transmission数据到kernel空间,Binder再把数据从内核拷贝到目标进程,这是通过copy_from_user和copy_to_user来实现的。data transaction过程如图5.4


5.4.3 Further Mechanism

Binder kernel命令BC_INCREFS,BC_RELEASE和BC_DECREFS实现Binder framework的引用计数功能。

link to death和death notification 功能也在kernel driver中实现了,kernel driver维护和管理 识别和分发Binder node结束的必要信息。命令BC_REQUEST_DEATH_NOTIFICIATION, BC_CLEAR_DEATH_NOTIFICATION, BC_DEAD_BINDER_NODE以及他们的请求码。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 出口货物被海关扣了说仿牌怎么办 有一批仿牌被宁波海关查了怎么办 付了定金不想要车了怎么办 泥墙刮石灰上涂料现在刮腻子怎么办 月经最后一天同房了怎么办吃什么药 奶水太多了宝宝总是呛到了怎么办 婴儿刚吃完奶大量喷奶怎么办 我干活细致领导说我慢怎么办 怀孕初期吃了加明矾的粉皮怎么办 绿豆面黄豆面白面蒸馒头怎么办 画油画时把颜料染在衣服上怎么办 买的布衣柜少了一个管子怎么办 小2球刚好进2球怎么办 大2球刚好进2球怎么办 大球2进了2球怎么办 身上剩的几百块钱有掉了怎么办 刚买一天的手机电板有问题怎么办 宝宝长湿疹穿少了就感冒怎么办 照片跟视频被孩子删了怎么办 老公总是说一些不开心的话题怎么办 孩子沉迷手机篮球课不爱去怎么办 坐久了屁鼓会长疮怎么办 套胶的胶皮与海绵分离怎么办 换肾15天了沒尿怎么办? 妻子的绒癌怎么办?——急人! 孕妇结石掉在输尿管有血尿怎么办 吃葯时药片沾在食管臂上怎么办 八十多了膀胱癌手术复发了怎么办 尿蛋白和尿隐血2个加怎么办 小肝癌手术后两个月又复发了怎么办 膀胱癌血尿堵塞尿道和尿管怎么办 肾炎腰疼一条腿疼尿血怎么办 孕晚期尿常规检查尿蛋白高怎么办? 腰开车疼的不会动了怎么办 小孩跑完满头大汗就咳嗽怎么办 小孩剧烈咳嗽喘吃了药不管用怎么办 做什么事都有点轻微的手抖怎么办 见到喜欢的人做事情就手抖怎么办 做了尿结石手术还尿血怎么办 宝宝十一个大运动发展缓慢怎么办 一岁八个月宝宝肚里有蛔虫怎么办