Android 内核初识(8)Binder
简介
Binder是Android系统提供的一种IPC(进程间通信)机制。由于Android是基于Linux内核的,因此,除了Binder外,还存在其他的IPC机制,例如管道和socket等。Binder相对于其他IPC机制来说,就更加灵活和方便了。Android系统基本上可以看作是一个基于Binder通信的C/S架构。Binder就像网络一样,把系统各个部分连接在了一起,因此它是非常重要的。
什么是Binder
Binder是android在内核中专门用于完成进程间通信而设置的一个虚拟设备(/dev/binder).
· ProcessState的构造函数悄悄地打开了Binder设备.每个进程只有一个ProcessState对象Process::self();
· 打开/dev/binder设备,这就相当于与内核的Binder驱动有了交互的通道。
· Binder的驱动代码在kernel/drivers/staing/android/binder.c中,另外该目录下还有一个binder.h头文件。
· /proc/binder目录下的内容可用来查看Binder设备的运行状况。
· 由于ProcessState的惟一性,因此一个进程只打开设备一次。
Client、Server和ServiceManager
在基于Binder通信的C/S架构体系中,除了C/S架构所包括的Client端和Server端外,Android还有一个全局的ServiceManager端,它的作用是管理系统中的各种服务(Service)。Client、Server和ServiceManager这三者之间的交互关系,如图所示

注意:一个Server进程可以注册多个Service,就像即将讲解的MediaServer一样。
根据上图,可以得出如下结论:
· Server进程要先注册一些Service到ServiceManager中,所以Server是ServiceManager的客户端,而ServiceManager就是服务端了。
· 如果某个Client进程要使用某个Service,必须先到ServiceManager中获取该Service的相关信息,所以Client是ServiceManager的客户端。
· Client根据得到的Service信息建立与Service所在的Server进程通信的通路,然后就可以直接与Service交互了,所以Client也是Server的客户端。
· 最重要的一点是,三者的交互都是基于Binder通信的,所以通过任意两者之间的关系,都可以揭示Binder的奥秘。
这里,要重点强调的是Binder通信与C/S架构之间的关系。Binder只是为C/S架构提供了一种通信的方式,我们完全可以采用其他IPC方式进行通信,例如,系统中有很多其他的程序采用的就是Socket或Pipe的方法进行进程间通信。很多初学者可能觉得Binder较复杂,尤其是看到诸如BpXXX、BnXXX之类的定义便感到头晕,这很有可能是把Binder通信层结构和应用的业务层结构搞混了。如果能搞清楚这二者的关系,完全可以自己实现一个不使用BpXXX和BnXXX的Service。须知,ServiceManager可并没有使用它们。
BpBinder和BBinder
BpBinder和BBinder都是Android中与Binder通信相关的代表,它们都从IBinder类中派生而来,如图

· BpBinder是客户端用来与Server交互的代理类,p即Proxy的意思。
· BBinder则是proxy相对的一端,它是proxy交互的目的端。如果说Proxy代表客户端,那么BBinder则代表服务端。这里的BpBinder和BBinder是一一对应的,即某个BpBinder只能和对应的BBinder交互。我们当然不希望通过BpBinderA发送的请求,却由BBinderB来处理。
· Binder系统通过handler来对应BBinder,在整个Binder系统中handler为0代表的就是ServiceManager所对应的BBinder.
MS(MediaServe)与SM(ServiceManager)用binder通信示例
在MediaServer进程向ServiceManager进程注册MediaPlayerService为例
在MediaServer进程中:
1,构造一个ProcessState,用ProcessState::self(),每个进程中只有一个ProcessState
2,ProcessState::self()中打开binder设备.
3,defaultServiceManager函数得到一个IServiceManager,实际得到BpServiceManager,它是IServiceManager的后代.用来和ServiceManager进程用binder通信,IServiceManager实际是用interface_cast函数模板,利用BpBinder对象作为参数新建了一个BpServiceManager对象.
4,用getStrongProxyForHandle(handler的值,0代表ServiceManager的BBinder),BpBinder和BBinder是一一对应的.Binder系统通过handler来对应BBinder
5,Android巧妙地通过DECLARE_META_INTERFACE和IMPLENT宏,将业务和通信牢牢地钩在了一起.DECLARE_META_INTERFACE在IServiceManager内部声明了业务函数.
6,addService函数中把请求数据打包成data后,传给了BpBinder的transact函数,把通信的工作交给了BpBinder.
7,在BpBinder的transact函数中使用了IPCThreadState
每个线程都有一个IPCThreadState,每个IPCThreadState中都有一个mIn、一个mOut,其中mIn是用来接收
来自Binder设备的数据的,而mOut则是用来存储发往Binder设备的数据的。
在ServiceManager进程中:
1,binder_open,打开binder设备
2,binder_become_context_manager,成为manager
3,binder_loop,处理客户端发过来的请求。
4,接收到请求,交给binder_parse,最终会调用func来处理这些请求
5,通常往binder_loop中传的那个函数指针是svcmgr_handler.这函数可集中处理.
6,do_add_service这个函数,它最终完成了对addService请求的处理实现
ServiceManager存在的意义
为何需要一个ServiceManager,其重要作用何在?
· ServiceManger能集中管理系统内的所有服务,它能施加权限控制,并不是任何进程都能注册服务。
· ServiceManager支持通过字符串名称来查找对应的Service。这个功能很像DNS。第6章 深入理解Binder
· 由于各种原因,Server进程可能生死无常。如果让每个Client都去检测,压力实在太大。现在有了统一的管理机构,Client只需要查询ServiceManager,就能把握动向,得到最新信息。这可能正ServiceManager存在的最大意义吧。
IServiceManager的家族

· IServiceManager、BpServiceManager和BnServiceManager都与业务逻辑相关。
· BnServiceManager同时从BBinder派生,表示它可以直接参与Binder通信。
· BpServiceManager虽然从BpInterface中派生,但是这条分支似乎与BpBinder没有关系。
· BnServiceManager是一个虚类,它的业务函数最终需要子类来实现。
重要说明:以上这些关系很复杂,但ServiceManager并没有使用错综复杂的派生关系,它直接打开Binder设备并与之交互。
Binder通信层和业务层的关系

Android 内核初识(8)Binder的更多相关文章
- 【转】Android 内核初识(6)SystemServer进程
简介 SystemServer的进程名实际上叫做“system_server”,通常简称为SS. 系统中的服务驻留在其中,常见的比如WindowManagerServer(Wms).ActivityM ...
- Android 内核初识(6)SystemServer进程
简介 SystemServer的进程名实际上叫做“system_server”,通常简称为SS. 系统中的服务驻留在其中,常见的比如WindowManagerServer(Wms).ActivityM ...
- Android 内核初识(5)Zygote进程
简介 Zygote本身是一个Native的应用程序,和驱动.内核等均无关系.Zygote是由init进程根据init.rc文件中的配置项而创建的. zygote最初的名字叫“app_process”, ...
- Android 内核初识(3)init进程
init是一个进程,确切地说,它是Linux系统中用户空间的第一个进程.由于Android是基于Linux内核的,所以init也是Android系统中用户空间的第一个进程,它的进程号是1.作为天字第一 ...
- Android 内核初识(1)下载源码需求与教程
官方文档: http://source.android.com/source/requirements.html Requirements The Android build is routinel ...
- Android 内核初识(7)RefBase、LightRefBase、sp和wp
简介 RefBase是Android中所有对象的始祖,类似MFC中的CObject及Java中的Object对象.在Android中,RefBase结合sp和wp,实现了一套通过引用计数的方法来控制对 ...
- Android 内核初识(4)属性服务器
简介 Windows平台上有一个叫注册表的东西.注册表可以存储一些类似key/value的键值对.一般而言,系统或某些应用程序会把自己的一些属性存储在注册表中,即使下次系统重启或应用程序重启,它还能够 ...
- Android 内核初识(2)android系统架构
以模块角度 以Java,native,kernel角度
- 写给 Android 应用工程师的 Binder 原理剖析
写给 Android 应用工程师的 Binder 原理剖析 一. 前言 这篇文章我酝酿了很久,参考了很多资料,读了很多源码,却依旧不敢下笔.生怕自己理解上还有偏差,对大家造成误解,贻笑大方.又怕自己理 ...
随机推荐
- xmlDoc.SelectNodes用法(获取不到节点时注意事项)
注:以下举例仅针对xml自定义了命名空间的情况,如果是其他情况,请参照他人博客~ using System;using System.Collections.Generic;using System. ...
- ### 学习《C++ Primer》- 7
Part 7: 重载运算与类型转换(第14章) // @author: gr // @date: 2015-01-08 // @email: forgerui@gmail.com 一.重载运算符要求 ...
- 禁用Linux bash rm --force
防止无意的Linux bash rm --force 二.禁用rm -rf 因为rm -rf 删除文件的时候,经常会不小心将系统文件或者多个有用的目录删除掉.有两种方法:1,每次删除都用-i(inte ...
- [leetcode]352. Data Stream as Disjoint Intervals
数据流合并成区间,每次新来一个数,表示成一个区间,然后在已经保存的区间中进行二分查找,最后结果有3种,插入头部,尾部,中间,插入头部,不管插入哪里,都判断一下左边和右边是否能和当前的数字接起来,我这样 ...
- Trie,HDU1875world puzzle
附上代码 #include<iostream> #include<cstdio> #include<string> #include<cstring> ...
- Asp.net 导入Excel数据
前台代码: <body> <form id="form1" runat="server"> <div> <asp:Fi ...
- java集合——进度1
集合类的由来: 对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定. 就使用集合容器进行存储. 集合特点:1,用于存储对象的容器.2,集合的长度是可变的.3,集合中不可以存 ...
- Cassandra1.2文档学习(10)—— 插入和更新数据
参考数据:http://www.datastax.com/documentation/cassandra/1.2/webhelp/index.html#cassandra/dml/dml_about_ ...
- Andorid游戏2048开发(一)
最近有一款Android平台下的游戏很是火爆----2048.下面记录一下开发过程.由于笔者是Android开发的初学者,所以希望借以此文熟悉整个Android开发的流程. 首先创建Game2048的 ...
- 摘自淘宝的js地区组件
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...