Binder驱动的原理和实现
通过上一节的介绍,大家应该对Binder有了基本的认识了。任何上层应用程序接口和用户操作都需要底层硬件设备驱动的支持,并为其提供各种操作接口。本节首先从Binder的驱动实现人手,分析其原理和它提供给用户层使用的接口。
Binder驱动的原理
为了完成进程间通信,Binder采用了AIDL(Android Interface Definition Language)来描述进程间的接口。在实际的实现中,IBinder是作为一个特殊的字符型设备而存在的,设备节点为
/dev/binder,其实现遵循Linux设备驱动模型,实现代码主要涉及以下文伴:
(1)kemel/drivers/staging/binder.h
(2)kernel/drivers/staging/binder.c
在其驱动的实现过程中,主要通过bjnder ioctl函数与用户空间的进程交换数据。BINDER WRITE.- READ用来读写数据,数据包中有一个cmd域用于区分不同的请求。binder thread_ write函数用于发送请求或返回结果,而binder thread read函数则用于读取结果。

在binder thread—write函数中调用binder transaction函数来转发请求并返回结果。当收到请求时,binder transaction函数会通过对象的handle找到对象所在的进程,如果handle为空,就认为对象是context__ mgr,把请求发给context_mgr所在的进程。请求中所有的Binder对象全部放到一个RB树中,最后把请求放到目标进程的队列中,等待目标进程读取。数据的解析工作放在binder_parser中实现;关于如何生成context__ mgr,内核中提供了BINDER。SET_ CONTEXTMGR命令来完成此项功能。下面我们就来看看Binder驱动究竟是如何实现的。
3.2.2 Blnder驱动的实现
上面我们已经对Binder驱动的原理进行了分析,在开始分析驱动的实现之前,我们还是通过一个例子来说明Binder在实际应用中应该如何运用,以及它能帮我们解决什么样的问题。这样会更容易帮助大家理解Binder驱动的实现。比如,A进程如果要使用B进程的服务,B进程首先要注题此服务,A进程通过Binder荻取该服务的hanlde,通过这个handle,A进程就可以使用该服务了。此外,你可以把handle理解成地址。A进程使用B进程的服务还意味着二者遵循相同的协议,这个协议反映在代码上就是二者要实现IBinder接口。
1.“对象”与“引用”
Binder不仅是Android系统中的一个完善的IPC机制,它也可以被当作Android系统的一种RPC(远程过程调用)机制,因为Binder的功能就是在本地“执行”其他进程的功能。因此,进程在通过Binder获取将要调用的进程服务时,可以是一个本地对象,也可以是一个远程服务的“引用”。这一点可能比较难以理解,稍候就会为大家分析,这里就先记住Binder不仅可以与本地进程通信,还可以与远程进程通信;这里的本地进程就是我们所说的本地对象,而远程进程则是我们所说的远程服务的一个“引用”。Binder的实质就是要把对象从一个进程映射到另一个进程中,而不管这个对象是本地的还
是远程的。如果是本地对象,更好理解;如果是远程对象,就按照我们上面所讲的来理解,即将远程对象的“引用”从一个进程映射到另一个进程中,于是当使用这个远程对象时,实际上
就是使用远裎对象在本地的一个“引用”,类似于把这个远程对象当作一个本地对象在使用。这也就是Binder与其他IPC机制不同的地方。
这个本地“对象”与远程对象的“引用”有什么不同呢?本地“对象”表示本地进程的地址空间的一个地址,而远程对象的“引用”则是一个抽象的32位句柄。它们之间是互斥的:
所有的进程本地对象都是本地进程的一个地址( address、ptr、binder),所有的远程进程的对象的“引用”都是一个句柄。对于发送者进程来说,不管是“对象”还是“引用”,它都会认为被发送的Binder对象是一个远程对象的句柄(即远程对象的“引用”)。但是,当Binder对象的数据被发送至日远端接收进程时,远端接收进程则会认为该Binder对象是一个本地对象地址(即本地对象)。正如我们之前说的,当Binder对象被接收进程接收后,不管该Binder对象是
 “引用”这个词并不是官方所描述的,而是笔者为了方便大家理解,将其称为引用,或许你有更好的描述。

本地的还是远程的,它都会被当作一个本地进程来处理。因此,从第三方的角度来说,尽管名称不同,对于一次完整的Binder调用,都将指向同一个对象,Binder驱动则负责两种不同名称的对象的正确映射,这样殖能把数据发送给正确的进程进行通信。这个映射关系也是进程间引用对象的基础,对一个对象的引用,在远程是句柄,在本地则是地址(即本地对象的地址)。下面我们先介绍分析该机制中所使用的数据结构体,然后再对整个流程进行分析。
2.loincier Work
首先来看一个最简单也是最基础的结构体binder work,其定义如代码清单3-1所示。
代码清单3-1 binder vork定义
struct /oinder_work {
struct list head entry;
enum {
BINDER_WORK_TRANSACT工ON = l,
BINDER _WORK_TRANSACTION_COMPLETE ,
B工NDER_WORK_NODE ,
BINDER_WORK_DEAD_BINDER,
BINDER_WORK_DEAD_BINDER_AN D_CLEAR r
BINDER WORK CLEAR DEATH NOTIFICATION,
} type;
萁中entry被定义为list head,用来实现一个双向链表,存储所有binder work的队列;此外,还包含一个enum类型的type,表示binder work的类型,后文会对这些类型进行详细分析,
大家就会觉得它更像是一个用来表示状态的enum。
3.Binder的类型
Binder的类型是使用定义在binder.h头文件中的一个enum来表示的,定义如代码清单3-2
所示。
代码清单3-2 Binder类型
#define B_PACK_CHARS (cl, c2, c3, c4) \
#define B TYPE LARGE Ox85
enum {
BINDER TYPE BINDER =B PACK_CHARS(’s’, ’b’, ’★’,B_TYPE_LARGE),
BINDER TYPE WEAK BINDER =B PACK CHARS( 'W', 'b', ’★’,B_TYPE_lARGE),
BINDER TYPE HANDLE =B PACK_CHARS(’s’, 'h', ’★’, B_TYPE_LARGE),
BINDER TYPE WEAK HANDLE =B PACK CHARS( 'W', 'h!, ’★’, B_TYPE_LARGE),
BINDER TYPE FD =B PACK_CFiARS(7f’, ’d’, ’★’,B_TYPE_LARGE),
};
从上面的代码可以看出,Binder被分成了5个不同的类型,但是仔细一看却是3个不同的大类,它们分别是:本地对象(BINDER TYPE BINDER. BINDER TYPE l;VEAK BINDER).

远程对象的“引用”( BINDEIL TYPE HANIDLE、BINDER TYPE WEAK HANDLE)的文件
( BINDER—TYPE FD)。前面两种都是我们刚刚分析过的,下面主要分析最后一种——文件(BINDER_ TYPE FD)。如果传递的是BINDER TYPE FD类型,其实还是会将文件映射到句
柄上,根据此fd找到对应的文件,然后在目标进程中分配一个fd,最后把这个fd赋值给返回的句柄。
4。Binder对象
我们把进程之间传递的数据称之为Binder对象(Binder Object),它在对应源码中使用
flat binder_object结构体(位于binder.h文件中)来表示,其定义如代码清单3-3所示。
代码清单3-3 flat_binder_object定义
struct flat_ binder_object {
unsigned long type;
unsigned long flags;
union t
void *obinder ;
signed long handle;
};
void *cookie;
该结构体中的type字段描述的是Binder的粪型,传输的数据是一个复用数据联合体。对于Binder类型,数据就是一个Binder本地对象;HANDLE类型,就是一个远程的handle句柄。
本地Binder对象和远程handle句柄比较难以理解,这里我们再次举例说明:假如A有个对象O,对于A来说,O就是一个本地的Binder对象;如果B想访问A的O对象,对于B来说,O就是一个handle。因此,从根本上来说,handle和Binder都指向O。如果是本地对象,Binder还可以带有额外的数据,这些数据将被保存到cookie字段中。flags字段表示传输方式,比如同步和异步等,其值同样使用一个enum来表示,定义如代码清单3-4所示。其中TF ONEWAY表示单向传递,是异步的,不需要返回;TFROOT OBJECT表面;内容是一个组建的根对象,对应类型为本地对象Binder; TF STATUS CODE表示内容是一个32位的状态码,将对应类型为远程对象的“引用”(即句柄handle); TF ACCEPT FDS表面;可以接收一个文件描述符,对应的类型为文件(BIND嚣R TYPE FD),即handle中存储的为文件描述符。

5. lobinder transaction ciata
其实我们并没有从flat binder_object结构体中看到Binder对象所传递的实际内容,因为Binder对象所传递的实际内容是通过另外一个结构体binder transaction data来表示的,其定义如代码清单3-5所示。
代码清单3-5 binder_transaction—data定义
structbinder—transaction_data {
union{
size—t handle;
void xptr;
) target;
void *cookie;
unsigned int code;
unsigned int flags;
pid_t sender_pid;
uid—t sender—euid;
size—t data—size;
size—t offsets—size;
union f
struct f
const void *buffer;
const void *offsets;
} ptr;
uint8一t buf[8];
} data;
}j
该结构体是理解Binder驱动实现的关键,下面将详细地对一个重要的数据进行分析。其中target字段又足一个复合联合体对象,target字段中的handle是要处理此事件的目标对象的句柄,根据此handle,Binder驱动可以找到应该由哪个进程处理此事件,并且把此事件的任务分发给一个线程,而那个线程也正在执行ioctl的BINDER- WRITE_ READ操作,即正在等待一个请求(见3.1节和3.2.1节),处理方法将稍候分析。target的ptr字段与handle对应,对于请求方,使用handle来指出远程对象;对于响应方,使用ptr来寻址,以便找到需要处理此事件的对象。所以handle和ptr是一个事物的两种表达(正如前面所说的本地对象和远程对象的“引用”),handle和ptr之间的翻译(解析)关系正是Binder驱动需要维护的(在binder_ transaction函数中,稍候分析)。
另外,该结构体中的cookie字段表示target对象所附加的额外数据;code是一个命令,它描述了请求Binder对象执行的操作;flags字段描述了传输的方式与flat binder_object中的flags字段对应;sender_pid和sender_ euid表示该进程的pid和uid;data size裹示数据的大小字节数;offsets_ size表示数据的偏移量字节数;最后一个union数据data表示真正的数据,其中ptr表看;与target->ptr对应的对象的数据,buf表示与handle对象对应的数据,data中的ptr中的buffer

Anciroid的IPC机制-Binder原理的更多相关文章

  1. Anciroid的IPC机制-Binder概述

    在Linux系统中,是以进程为单位分配和管理资源的.出于保护机制,一个进程不能直接访问另一个进程的资源,也就是说,进程之间互相封闭.但是,在一个复杂的应用系统中,通常会使用多个相关的进程来共同完成一项 ...

  2. IPC机制--Binder

    文章来自 Android技术内幕 系统卷 转:http://www.linuxidc.com/Linux/2011-08/40508.htm 什么是IPC机制以及IPC机制的种类 在Linux中,是以 ...

  3. Android IPC机制—Binder的工作机制

    进程和线程的关系 IPC机制即为跨进程通信,是inter-Process Communication的缩写.是指两个进程之间进行通信.在说进程通信之前,我们的弄明白什么是线程,什么是进程.进程和线程是 ...

  4. 第二章——第二节 IPC机制的概述和使用

    一.Serialiable与Paracle ①.作用    ②.使用 二.Binder与AIDL ①.各自的作用 三.如何使用IPC机制 举例 四.IPC机制的原理 ①.流程图  ②.自己编译自动生成 ...

  5. Linux下IPC机制

    Linux下IPC机制 实践要求 研究Linux下IPC机制:原理,优缺点,每种机制至少给一个示例,提交研究博客的链接 共享内存 管道 FIFO 信号 消息队列 IPC 进程间通信(IPC,Inter ...

  6. linux IPC机制学习博客

    要求 研究Linux下IPC机制:原理,优缺点,每种机制至少给一个示例,提交研究博客的链接 - 共享内存 - 管道 - FIFO - 信号 - 消息队列 研究博客 管道(PIPE) 管道(PIPE): ...

  7. 大型项目必备IPC之Binder机制原理(一)

    阿里P7Android高级架构进阶视频免费学习请点击:https://space.bilibili.com/474380680 摘要 Binder是Android系统进程间通信(IPC)方式之一.Li ...

  8. 浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6621566 上一篇文章Android进程间通信 ...

  9. Android进程间通信(IPC)机制Binder简要介绍和学习计划

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6618363 在Android系统中,每一个应用 ...

随机推荐

  1. Slickflow.NET 开源工作流引擎高级开发(三) -- 并行分支容器与会签工作流模式的组合

    前言:  流程引擎的核心功能是负责解析流程定义XML和流转,业务环节的不断积累,让人们不断总结和抽象出一些模式,这些模式统称为工作流模式(Workflow Pattern).本文的重点就是介绍一种常见 ...

  2. 群晖NAS使用Docker安装迅雷离线下载出现the active key is not valid.

    出现这种情况多半是挂了,也有可能是不稳定的网络,重装Docker镜像可能会解决,只有不断试,没什么好的解决方法.

  3. [原创]浅谈H5页面测试介绍

    [原创]浅谈H5页面测试介绍 目前移动互联网非常火热,除了各种App,H5也是非常热,由于H5跨平台,且版本更新容易,做为引流或获客是非常好的一种简单低成本平台:今天来谈谈H5页面测试都要测试什么? ...

  4. MongoDB简单使用 —— 驱动

    C#中可以通过官方的驱动MongoDB.Drvier来使用,使用Nuget安装即可. Install-Package MongoDB.Driver Bson文档操作: using MongoDB.Bs ...

  5. C# WINFORM的自动更新程序

    自动更新程序AutoUpdate.exe https://git.oschina.net/victor596jm/AutoUpdate.git 1.获取源码 http://git.oschina.ne ...

  6. [Winform]Media Player播放控制面板控制,单击事件截获

    摘要 在项目中有这样的一个需求,需要在一台宣传机器上循环播放一段视频,并在体验的用户单击鼠标左键的时候推出全屏,可以让用户体验电脑的其它功能. 解决方案 考虑到都是windows系统的,所以采用了wi ...

  7. WiX: uninstall older version of the application

    I have installer generated by WiX and I want it to ask: "You have already installed this app. D ...

  8. 统计代码执行时间,使用Stopwatch和UserProcessorTime的区别

    当我们需要统计一段代码的执行时间,首先想到的可能是Stopwatch类.在这里,先暂不使用Stopwatch,自定义一个统计代码执行时间的类,大致需要考虑到: 1.确保统计的是当前进程.当前线程中代码 ...

  9. 从零开始,运行一个android例子程序

    电脑上连个eclipse都没装,怎么玩android?一穷二白的你, 下面就跟随我,从零开始,一步一步操作,运行我们的第一个android应用程序.我一直相信,学习开发,只有在调试过程中学的是最快的. ...

  10. VisualStudio:让 XML 支持智能提示

    将 XSD 文件拷贝到 VS 下的指定目录,我的电脑上的目录为:C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages ...