android binder学习 笔记(图文)
- 格式:pdf
- 大小:592.32 KB
- 文档页数:29
Android图⽂详解Binder进程通信底层原理⽬录什么是进程间通信什么是 BinderAndroid 中 IPC 的⽅式Binder 优势Linux 传统的 IPC 原理基本概念进程隔离进程空间划分系统调⽤传统 IPC 通信原理Binder IPC原理Binder 采⽤分层架构设计Binder 驱动Binder IPC 内存映射Android Binder 原理图Bind 原理图Bind 原理图交互Bind 原理图交互路线之前了解到进程与多进程,涉及多进程不可避免的遇到了进程间通信,说到进程间通信,Binder 成了⼀道绕不过的坎。
接下来咱们逐⼀了解。
什么是进程间通信进程间通信(IPC,Inner Process Comunication),就是指不同进程之间的信息传递。
进程是系统进⾏资源分配和调度的基本单位,是操作系统的结构的基础;⼀个应⽤⾄少有⼀个进程,⼀个进程中有包含了多个线程(线程是CPU调度的最⼩单位),进程相当于是线程的ViewGroup,线程相当于操作系统分配个进程的View。
什么是 BinderBinder 是 Android 系统中进程间通信机制(IPC)的⼀种⽅式,它是这些进程间通讯的桥梁。
正如其名"粘合剂"⼀样,它把系统中各个组件粘合到了⼀起,是各个组件的桥梁。
应⽤层:是⼀个能发起通信的Java类。
Client:是对 Binder 代理对象,是 Binder 实体对象的⼀个远程代理。
Server:是 Server 中的 Binder 实体对象。
机制:是⼀种进程间通信机制。
驱动:是⼀个虚拟物理设备驱动;如startActivity的简图:这⾥就⽤到了 Binder 通信,你会发现这⾥还有 Socker 通信,那我为什么要⽤ Binder ⽽不⽤ Socket。
Android 中 IPC 的⽅式名称特点使⽤场景Bundle只能传输实现了序列化或者⼀些Android⽀持的特殊对象适合⽤于四⼤组件之间的进程交互⽂件不能做到进程间的即时通信,并且不适合⽤于⾼并发的场景适合⽤于SharedPreference以及IO操作ContentProvider可以访问较多的数据,⽀持⼀对多的⾼并发访问,因为ContentProvider已经⾃动做好了关于并发的机制适合⽤于⼀对多的数据共享并且需要对数据进⾏频繁的CRUD操作Socket通过⽹络传输字节流,⽀持⼀对多的实时通信,但是实现起来⽐较复杂适合⽤于⽹络数据共享Messenger底层原理是AIDL,只是对其做了封装,但是不能很好的处理⾼并发的场景,并且传输的数据只能⽀持Bundle类型多进程、单线程且线程安全AIDL功能强⼤,使⽤Binder机制,⽀持⼀对多的⾼并发实时通信,但是需要处理好线程同步⼀对多并且有远程进程通信的场景Binder 优势出发点Binder共享内存Socket性能拷贝⼀次⽆需拷贝拷贝两次特点基于C/S架构,易⽤性⾼控制复杂,易⽤性差基于C/S架构,通⽤接⼝,传输效率低、开销⼤安全每个APP分配UID,同时⽀持实名和匿名依赖上层协议,访问接⼊点是开放的不安全依赖上层协议,访问接⼊点是开放的不安全通过以上对⽐,Android 最终选择了⾃建⼀套兼顾好⽤、⾼效、安全的 Binder。
Android进程间通信-Binder机制目录一.简要介绍和学习计划二.Service Manager成为Binder守护进程之路三.Server和Client获得Service Manager接口之路四.Server启动过程源代码分析五.Client获得Server远程接口过程源代码分析六.应用程序框架层的Java接口源代码分析一、Android进程间通信(IPC)机制Binder 简要介绍和学习计划我们知道,在Android系统中,每一个应用程序都是由一些Activity和Service组成的,一般Service 运行在独立的进程中,而不同的Activity有可能运行在同一个进程中,也可能运行在不同的进程中。
这很自然地想到,不在同一个进程的Activity和Service是如何通信的呢?毕竟它们要协作在一起来完成一个完整的应用程序功能。
这就是本文中要介绍的Android系统进程间通信机制Binder了。
我们知道,Android系统是基于Linux内核的,而Linux内核继承和兼容了丰富的Unix系统进程间通信(IPC)机制。
有传统的管道(Pipe)、信号(Signal)和跟踪(Trace),这三项通信手段只能用于父进程与子进程之间,或者兄弟进程之间;后来又增加了命名管道(Named Pipe),使得进程间通信不再局限于父子进程或者兄弟进程之间;为了更好地支持商业应用中的事务处理,在AT&T的Unix 系统V中,又增加了三种称为“System V IPC”的进程间通信机制,分别是报文队列(Message)、共享内存(Share Memory)和信号量(Semaphore);后来BSD Unix对“System V IPC”机制进行了重要的扩充,提供了一种称为插口(Socket)的进程间通信机制。
若想进一步详细了解这些进程间通信机制,建议参考Android学习启动篇一文中提到《Linux内核源代码情景分析》一书。
AndroidFramework学习(四):Binder机制与代理模式Binder是Android的进程间通信核⼼,Android的各种核⼼服务都是通过Binder机制进⾏相互通信的。
熟悉Binder机制话就会知道,Binder的client部分就是通过代理模式来访问Server端的。
本⽂我们就结合代理模式来详细讲解⼀下Java层Binder机制。
⼀、代理模式介绍相信⼤家对设计模式都有⼀定的了解,这⾥我就不对代理模式进⾏过多的赘述了。
这⾥我们只在阐释⼀下代理模式的使⽤场景:远程代理(Remote Proxy):如果某个对象⽆法实例化,不在同⼀个地址空间,需要通过编码来进⾏通信。
⽐如需要访问⽹络服务器上⾯的⼀个对象操作,⽐如Binder。
虚代理(Virtual Proxy):在需要的时候创建⼤对象,⽐如超⼤图⽚,我们可以使⽤⼀个虚代理代理图像,在真正需要的时候再去将图像完全加载出来,在这之前只需要在代理⾥⾯保存图像的⼤⼩,让它有个占位就好了。
保护代理(Protect Proxy):需要对对象的某些操作进⾏隐藏,那么就可以使⽤代理对它的接⼝进⾏隐藏。
智能指引(Smart Reference):当需要对对象的引⽤进⾏计数的时候,可以使⽤智能指引的代理模式。
⼆、Binder机制Binder是⼀个接⼝形式的IPC。
这⾥以Android开发过程中使⽤的.aidl⽂件声明⽣成的接⼝为例。
例如,我们在Client端声明了⼀个IUserVerifyInterface.aidl,⽤于向服务端发起⽤户校验:// IUserVerifyInterface.aidlpackage com.renhui.aidl;import er;// Declare any non-default types here with import statementsinterface IUserVerifyInterface {boolean verifyUser(in User user);}在编译运⾏之前,编辑器会⾃动⽣成相关的类 IUserVerifyInterface.Stub 和 IUserVerifyInterface.Proxy,通过调⽤bindService就可以得到Binder的代理。
Android深⼊浅出之Binder机制Android深⼊浅出之Binder机制⼀说明Android系统最常见也是初学者最难搞明⽩的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的。
所以搞明⽩Binder的话,在很⼤程度上就能理解程序运⾏的流程。
我们这⾥将以MediaService的例⼦来分析Binder的使⽤:l ServiceManager,这是Android OS的整个服务的管理程序l MediaService,这个程序⾥边注册了提供媒体播放的服务程序MediaPlayerService,我们最后只分析这个l MediaPlayerClient,这个是与MediaPlayerService交互的客户端程序下⾯先讲讲MediaService应⽤程序。
⼆ MediaService的诞⽣MediaService是⼀个应⽤程序,虽然Android搞了七七⼋⼋的JAVA之类的东西,但是在本质上,它还是⼀个完整的Linux操作系统,也还没有⽜到什么应⽤程序都是JAVA写。
所以,MS(MediaService)就是⼀个和普通的C++应⽤程序⼀样的东西。
MediaService的源码⽂件在:framework\base\Media\MediaServer\Main_mediaserver.cpp中。
让我们看看到底是个什么玩意⼉!int main(int argc, char** argv){//FT,就这么简单??//获得⼀个ProcessState实例sp<ProcessState> proc(ProcessState::self());//得到⼀个ServiceManager对象sp<IServiceManager> sm = defaultServiceManager();MediaPlayerService::instantiate();//初始化MediaPlayerService服务ProcessState::self()->startThreadPool();//看名字,启动Process的线程池?IPCThreadState::self()->joinThreadPool();//将⾃⼰加⼊到刚才的线程池?}其中,我们只分析MediaPlayerService。
安卓进程间通信的四种方式(含案例)1. BinderBinder是Android系统中的一种轻量级的进程间通信机制。
它基于C++语言实现,允许多个进程共享数据和调用彼此的方法。
Binder有三个角色:服务端、客户端和服务管理器。
服务端提供服务并注册到服务管理器,客户端通过服务管理器获取服务对象并进行通信。
例如,一个应用可能需要使用另一个应用提供的服务,通过Binder可以跨进程访问服务的方法。
服务端可以实现一个抽象类,并将其注册到服务管理器,客户端通过服务管理器获取服务对象,并调用其方法。
2. ContentProviderContentProvider是Android提供的一种数据共享机制,能够使一个应用程序的数据集对其他应用程序可见。
ContentProvider提供了一系列的方法,允许其他应用程序通过URI进行数据的访问、插入、更新和删除。
例如,一个应用程序有一个存储用户信息的数据库,通过将ContentProvider暴露给其他应用程序,其他应用程序可以通过URI查询、插入、更新和删除用户信息。
3.广播广播是Android提供的进程间通信的一种方式。
广播通过Intent传递消息,发送广播的应用程序将消息发送给其他应用程序,并且其他应用程序可以通过注册广播接收器来接收这些消息。
例如,一个应用程序可能发送一个自定义广播来通知其他应用程序有关一些事件的发生,其他应用程序可以注册广播接收器来接收这个广播并执行相应的操作。
4. MessengerMessenger是一种轻量级的IPC机制,它是基于Binder实现的。
Messenger可以在不同的进程间发送Message对象,通过Message对象传递数据。
例如,一个应用程序可以创建一个Messenger实例,并将其传递给另一个应用程序,另一个应用程序可以通过Messenger向第一个应用程序发送消息,并通过消息携带数据。
以上是安卓进程间通信的四种方式,每种方式都有自己的特点和适用场景。
图解Android-Binder和Service在⼀⽂中我们说道,Zygote⼀⽣中最重要的⼀件事就是⽣下了 System Server 这个⼤⼉⼦,System Server 担负着提供系统 Service的重任,在深⼊了解这些Service 之前,我们⾸先要了解什么是Service?它的⼯作原理是什么?1. Service是什么?简单来说,Service就是提供服务的代码,这些代码最终体现为⼀个个的接⼝函数,所以,Service就是实现⼀组函数的对象,通常也称为组件。
Android 的Service 有以下⼀些特点:1. 请求Service服务的代码(Client) 和 Service本⾝(Server) 不在⼀个线程,很多情况下不在⼀个进程内。
跨进程的服务称为远端(Remote)服务,跨进程的调⽤称为IPC。
通常应⽤程序通过代理(Proxy)对象来访问远端的Service。
2. Service 可以运⾏在native 端(C/C++),也可以运⾏在Java 端。
同样,Proxy 可以从native 端访问Java Service, 也可以从Java端访问nativeservice,也就是说,service的访问与语⾔⽆关。
3. Android⾥⼤部分的跨进程的IPC都是基于Binder实现。
4. Proxy 通过 Interface 类定义的接⼝访问Server端代码。
5. Service可以分为匿名和具名Service. 前者没有注册到ServiceManager, 应⽤⽆法通过名字获取到访问该服务的Proxy对象。
6. Service通常在后台线程执⾏(相对于前台的Activity), 但Service不等同于Thread,Service可以运⾏在多个Thread上,⼀般这些Thread称为Binder Thread.要了解Service,我们得先从 Binder ⼊⼿。
2. Binder先给⼀张Binder相关的类图⼀瞰Binder全貌,从上⾯的类图(点击看⼤图)跟Binder⼤致有这么⼏部分:Native 实现: IBinder, BBinder, BpBinder, IPCThread, ProcessState, IInterface, etcJava 实现: IBinder, Binder, BinderProxy, Stub, Proxy.Binder Driver: binder_proc, binder_thread, binder_node, etc.我们将分别对这三部分进⾏详细的分析,⾸先从中间的Native实现开始。
Android Binder机制总结1Android组件化思想Android应用的体系结构是基于分布式组件模型。
Android应用中的组件之间是松耦合,具有模块化以及可扩展的特性。
这些组件可以同时运行在同一个进程中,也可以在不同的进程中。
如你编写的应用程序需要显示一个可以滚动的图片列表,如果其它某个应用程序已经开发了具有此功能的组件,并对外发布了此组件以使其它应用程序能够使用此组件,因此你可以直接调用这个组件来显示图片,而不需要重新开发一个具有此功能的组件。
另外一些系统服务如联系人列表、拍照、打电话等公共功能都能够在其它的应用程序中被调用。
2常见的进程通信方式(IPC)IPC是Inter-process communication的缩写形式,主要用于多进程间通信和数据交互。
a) Pipes(管道): Pipes are unidirectional byte-streams that connect the standard output from one process with the standard input of another process.b) Message Queues(消息队列): maintains a queue of messages to which processes can read to and write from, thereby achieving IPC.c) Shared Memory(共享内存): A common memory location which is accessible by all communicating processes. IPC is achieved by writing to and reading from the shared memory location.d) Semaphores(信号量): A semaphore is a shared variable on which processes can signal and wait thereby achieving IPC.e) Signals(信号): A process can send signals to processes with the same uid and gid or in the same process group.f) Sockets: Sockets are bidirectional communication streams. Two processes can communicate with byte-streams by opening the same socket.3Android中进程通信方式Android中的Binder机制源于OpenBinder,它的创造者是Dianne Kyra Hackborn,但是已经不再维护。
【济南中心】Android课程同步笔记day08:Android应用开发基础通过Bind方式来调用服务里的方法Android中提供了调用服务里的方法的解决方案,就是要获取到服务的代理服务返回其代理服务通过onBind()方法返回代理,其返回值是一个IBinder的实现类@Overridepublic IBinder onBind(Intent intent) {//绑定服务, 返回IBinder的中间人return new MyBinder();}创建一个IBinder的实现类,IBinder是一个接口,实现该接口我们需要实现里面所有的方法,非常不方便,系统为我们提供了一个方便的实现类Binder,让该类继承Binder,我们就可以提供代理方法了public class MyBinder extends Binder{public void callMethodInService(String name){methodInService(name);}}绑定服务获得其代理,调用服务里的方法public class MainActivity extends Activity {//代理人private MyBinder myBinder;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);}//绑定服务获取中间人public void bind(View view){//1. 绑定Service//intent 要绑定哪个Service//conn 通讯频道,通过该conn来获取服务的代理//BIND_AUTO_CREATE如果服务不存在,会把服务创建出来. //2. 要绑定哪个ServiceIntent intent = new Intent(this,TestService.class);bindService(intent, new MyConn(), BIND_AUTO_CREATE); }//3. 创建通讯频道private class MyConn implements ServiceConnection{//当服务被成功连接的时候调用的方法@Overridepublic void onServiceConnected(ComponentName name, IBinder service) { //4. 成功连接后,得到了服务的代理对象myBinder = (MyBinder) service;}//当服务失去连接的时候调用的方法.@Overridepublic void onServiceDisconnected(ComponentName name) {}}//通过中间人调用服务里面的方法public void call(View view){//5. 通过得到的代理对象,调用服务里的方法myBinder.callMethodInService("小华华", 250);}}绑定服务调用服务方法的步骤1.编写服务代码public IBinder onBind(Intent intent) {}2. 在服务内部定义一个代理人对象MyBinder代理人对象有一个方法可以间接的调用服务内部的方法3. 在onbind方法里面返回代理人对象4. 在Activity代码采用绑定的方式连接到服务bindService(intent, new MyConn(), BIND_AUTO_CREATE);5. 在serviceConnection的实现类里面有一个方法,获取到服务返回的代理人对象public void onServiceConnected(ComponentName name, IBinder service) 6. 强制类型转换IBinder转化成MyBinder类型myBinder = (MyBinder) service;7. 调用代理人对象的方法--间接调用了服务里面的方法通过接口隐藏代码内部实现的细节学习一种代码的设计方式,如果一个内部类有多个方法,我只想暴露出其中的一部分方法时,可以通过接口将想要暴露的方法暴露出去。
图⽂详解AndroidBinder跨进程通信机制原理⽬录⽬录1. Binder到底是什么?中⽂即粘合剂,意思为粘合了两个不同的进程⽹上有很多对Binder的定义,但都说不清楚:Binder是跨进程通信⽅式、它实现了IBinder接⼝,是连接ServiceManager的桥梁blabla,估计⼤家都看晕了,没法很好的理解我认为:对于Binder的定义,在不同场景下其定义不同定义在本⽂的讲解中,按照⼤⾓度 -> ⼩⾓度去分析Binder,即:先从机制、模型的⾓度去分析整个Binder跨进程通信机制的模型其中,会详细分析模型组成中的Binder驱动再从源码实现⾓度,分析Binder在Android中的具体实现从⽽全⽅位地介绍Binder,希望你们会喜欢。
2. 知识储备在讲解Binder前,我们先了解⼀些基础知识2.1 进程空间分配⼀个进程空间分为⽤户空间 & 内核空间(Kernel),即把进程内⽤户 & 内核隔离开来⼆者区别:1. 进程间,⽤户空间的数据不可共享,所以⽤户空间 = 不可共享空间2. 进程间,内核空间的数据可共享,所以内核空间 = 可共享空间进程内⽤户与内核进⾏交互称为系统调⽤⽰意图2.2 进程隔离为了保证安全性 & 独⽴性,⼀个进程不能直接操作或者访问另⼀个进程,即Android的进程是相互独⽴、隔离的2.3 跨进程通信(IPC)隔离后,由于某些需求,进程间需要合作 / 交互跨进程间通信的原理1. 先通过进程间的内核空间进⾏数据交互2. 再通过进程内的⽤户空间 & 内核空间进⾏数据交互,从⽽实现进程间的⽤户空间的数据交互⽰意图⽽Binder,就是充当连接两个进程(内核空间)的通道。
3. Binder 跨进程通信机制模型3.1 模型原理Binder跨进程通信机制模型基于Client - Server模式,模型原理图如下:相信我,⼀张图就能解决问题⽰意图3.2 额外说明说明1:Client进程、Server进程 & Service Manager进程之间的交互都必须通过Binder驱动(使⽤open和ioctl⽂件操作函数),⽽⾮直接交互 **原因:1. Client进程、Server进程 & Service Manager进程属于进程空间的⽤户空间,不可进⾏进程间交互2. Binder驱动属于进程空间的内核空间,可进⾏进程间 & 进程内交互所以,原理图可表⽰为以下:虚线表⽰并⾮直接交互⽰意图说明2:Binder驱动 & Service Manager进程属于Android基础架构(即系统已经实现好了);⽽Client进程和Server进程属于Android应⽤层(需要开发者⾃⼰实现)所以,在进⾏跨进程通信时,开发者只需⾃定义Client & Server进程并显式使⽤上述3个步骤,最终借助Android的基本架构功能就可完成进程间通信⽰意图说明3:Binder请求的线程管理Server进程会创建很多线程来处理Binder请求管理Binder模型的线程是采⽤Binder驱动的线程池,并由Binder驱动⾃⾝进⾏管理⽽不是由Server进程来管理的⼀个进程的Binder线程数默认最⼤是16,超过的请求会被阻塞等待空闲的Binder线程。
Binder学习——C实现注:基于Android5.1版本,Tiny4412平台。
⼀、学习笔记1.Binder的核⼼是IPC和RPCIPC: (Inter-Process Communication)进程间通信,指⾄少两个进程或线程间传送数据或信号的⼀些技术或⽅法。
RPC: (Remote-Process Communication)远程过程调⽤,类似于调⽤其它进程的函数。
ICP三要素:源:A⽬的:B向ServiceManager注册led服务A向ServiceManager查询led服务得到⼀个handle。
数据:buf[512]RPC:调⽤哪个函数:Server的函数编号传给它什么参数:通过IPC的buf[]进⾏传输(使⽤的是binder驱动)。
返回结果:远端执⾏完返回值2.系统⾃带的C实现的Binder程序:frameworks/native/cmds/servicemanagerservice_manager.c 充当SM的⾓⾊,管理所有的Service,其本⾝也是⼀个服务。
binder.c 封装好的C库bctest.c 半成品,演⽰怎样注册服务3.int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr)如果两个service的注册函数svcmgr_publish()的最后⼀个参数值相同,那么会报错。
正常情况下kill掉service_manager的时候,所有的service都会收到死亡通知,然后从链表中删除掉。
但是若两个service指定为相同的ptr,那么下次再重启service_manager的时候它会报这个服务已经存在了,由于相同的ptr导致kill掉service_manager时有⼀个并没有收到死亡通知,也就不能从链表中删除。
4.binder应该是个内核线程,binder驱动中创建了⼀个单CPU的⼯作队列# ps | grep binderroot 1073 2 0 0 c00a0668 00000000 S binder5.驱动中数据结构表⽰struct binder_ref : 表⽰引⽤binder_node :表⽰⼀个Servicebinder_proc :表⽰进程binder_thread :表⽰线程的⼀个线程6.handle是进程A(Client)对进程B(Service)提供的服务的引⽤,由handle可以对⽐desc成员找到binder_ref结构,其*node成员指向表⽰某项服务的binder_node结构体,binder_node的proc成员指向表⽰进程的binder_proc结构体,其内部指向对应的进程从⽽找到⽬的进程, 然后把数据给到⽬的进程的todo链表上,然后唤醒⽬的进程。
Android平台——Binder机制由代码来补充部分:int main(int argc, char** argv){sp<ProcessState> proc(ProcessState::self());sp<IServiceManager> sm = defaultServiceManager();LOGI("ServiceManager: %p", sm.get());AudioFlinger::instantiate();MediaPlayerService::instantiate();CameraService::instantiate();ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();}sp<ProcessState> proc(ProcessState::self()),这一行代码会建立ProcessState对象,一个进程只有唯一的一个ProcessState对象,而ProcessState类的作用是来打开/dev/binder设备。
这也就说明了一个问题,一个进程只不可能同时存在多个对/dev/binder的操作。
sp<IServiceManager> s m = defaultServiceManager(),这一行代码要做的事情参见上图。
1、创建一个BpBinder。
2、由BpBinder对象创建BpServiceManger对象。
(为什么要采取如此不自然的方式,可以看一下这两个对象继承的基类)。
完成这一步骤的最重要的作用在于以后对于IServiceManager对象的方法的调用,都将会由其子类BpServiceManger的方法来实现(这样做的意义何在?这样的作用仅仅在于我们可以重用IServiceManager的代码,别忘了我们还有一个类似的继承自IServiceManager的类,它叫做BnServiceManger)。
1.Android Binder介绍(1)Binder基于Client-Server通信模式。
Android Binder框架定义了四个角色:Server,Client,ServiceManager以及Binder驱动。
其中Server,Client,ServiceManager运行于用户空间,驱动运行于内核空间。
(2)Android Binder机制核心组件是Binder驱动程序,ServiceManager提供辅助管理功能,负责管理Server、向Client提供查询Server的功能。
(3)ServiceManager提供接口addService和getService。
2.ServiceManagerServiceManager也是Client-Server通信模式。
Java层ServiceManager是客户端,Server端对应Service_manager.c,这个一个Linux守护进程,系统引导的时候会开启的服务。
(启动方式见init.rc中service servicemanager /system/bin/servicemanager)3.ActivityManager4.Android Binder 框架5.AIDL 介绍(1)AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(inter process communication,IPC)的代码。
(2)AIDL接口文件,和普通的接口内容没有什么特别,只是它的扩展名为.aidl。
保存在src目录下。
如果其他应用程序需要IPC,则那些应用程序的src也要带有这个文件。
(3)何时使用AIDL:允许客户端从不同的应用程序为了进程间的通信而去访问service,并且想在service处理多线程。
(4)如果不需要进行不同应用程序间的并发通信(IPC),you should create yourinterface by implementing a Binder。
图1.数据结构关系图
图2.数据传输
图3.详细的流程图
图4.binder_transation_data结构体
图5.注意ptr的转变
图6.韩国人层次分的很细
图7.Parcel描述的不错
图8.binder_buffer
图9.flat_binder_object
图10.注册的流程,获取和使用的流程大致
图11.Binder的内在,在于IPC内存拷贝的次数少、效率高。
直观地罗列了Android binder机制中涉及的数据结构,以及相互之间的联系。
分了Java、JNI、C++、Driver四个层面。
但可以继续分层。
看图说话,希望能一目了然的展现Binder机制,You Know。
关于具体的逻辑,看源码吧。
如果看不清楚,可以联系jdan1004@!
reference:
《Android 系统源代码情景分析》
《Android 框架解密》
《深入Linux内核架构》。
AndroidBinder机制(超级详尽)1.binder通信概述binder通信是⼀种client-server的通信结构,1.从表⾯上来看,是client通过获得⼀个server的代理接⼝,对server进⾏直接调⽤;2.实际上,代理接⼝中定义的⽅法与server中定义的⽅法是⼀⼀对应的;3.client调⽤某个代理接⼝中的⽅法时,代理接⼝的⽅法会将client传递的参数打包成为Parcel 对象;4.代理接⼝将该Parcel发送给内核中的binder driver.5.server会读取binder driver中的请求数据,如果是发送给⾃⼰的,解包Parcel对象,处理并将结果返回;6.整个的调⽤过程是⼀个同步过程,在server处理的时候,client会block住。
2.service managerService Manager是⼀个linux级的进程,顾名思义,就是service的管理器。
这⾥的service是什么概念呢?这⾥的service的概念和init过程中init.rc中的service是不同,init.rc中的service是都是linux进程,但是这⾥的service它并不⼀定是⼀个进程,也就是说可能⼀个或多个service属于同⼀个linux进程。
在这篇⽂章中不加特殊说明均指android native端的service。
任何service在被使⽤之前,均要向SM(Service Manager)注册,同时客户端需要访问某个service时,应该⾸先向SM查询是否存在该服务。
如果SM存在这个service,那么会将该service 的handle返回给client,handle是每个service的唯⼀标识符。
SM的⼊⼝函数在service_manager.c中,下⾯是SM的代码部分int main(int argc, char **argv){struct binder_state *bs;void *svcmgr = BINDER_SERVICE_MANAGER;bs = binder_open(128*1024);if (binder_become_context_manager(bs)) {LOGE("cannot become context manager (%s)/n", strerror(errno));return -1;}svcmgr_handle = svcmgr;binder_loop(bs, svcmgr_handler);return 0;}这个进程的主要⼯作如下:1.初始化binder,打开/dev/binder设备;在内存中为binder映射128K字节空间;2.指定SM对应的代理binder的handle为0,当client尝试与SM通信时,需要创建⼀个handle为0的代理binder,这⾥的代理binder其实就是第⼀节中描述的那个代理接⼝;3.通知binder driver(BD)使SM成为BD的context manager;4.维护⼀个死循环,在这个死循环中,不停地去读内核中binder driver,查看是否有可读的内容;即是否有对service的操作要求, 如果有,则调⽤svcmgr_handler回调来处理请求的操作。
郝一二三笔记framework\base\Media\MediaServer \Main_mediaserver.cpp1.ProcessState:framework\base\libs\binder\ProcessState.cppsp<IServiceManager> defaultServiceManager(){if (gDefaultServiceManager != NULL) return gDefaultServiceManager; //又是一个单例,设计模式中叫singleton{AutoMutex _l(gDefaultServiceManagerLock);framework/base/include/binder/IInterface.hclass IServiceManager : public IInterface{public:DECLARE_META_INTERFACE(ServiceManager);virtual status_t ( const String16& name,const sp<IBinder>& service) = 0;};#define DECLARE_META_INTERFACE(INTERFACE) \static const android::String16 descriptor; \static android::sp<I##INTERFACE> asInterface( \const android::sp<android::IBinder>& obj); \virtual const android::String16& getInterfaceDescriptor() const; \I##INTERFACE(); \virtual ~I##INTERFACE();我们把它兑现到IServiceManager就是:static const android::String16 descriptor; //增加一个描述字符串static android::sp< IServiceManager >asInterface(const android::sp<android::IBinder>& obj) //增加一个asInterface函数virtual const android::String16& getInterfaceDescriptor() const; //增加一个get函数IServiceManager (); \virtual ~IserviceManager();//增加构造和虚析购函数...IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");下面是这个宏的定义#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \const android::String16 I##INTERFACE::descriptor(NAME); \const android::String16& \I##INTERFACE::getInterfaceDescriptor() const { \return I##INTERFACE::descriptor; \} \android::sp<I##INTERFACE> I##INTERFACE::asInterface( \const android::sp<android::IBinder>& obj) \{ \android::sp<I##INTERFACE> intr; \if (obj != NULL) { \intr = static_cast<I##INTERFACE*>( \obj->queryLocalInterface( \I##INTERFACE::descriptor).get()); \if (intr == NULL) { \intr = new Bp##INTERFACE(obj); \} \} \return intr; \} \I##INTERFACE::I##INTERFACE() { } \I##INTERFACE::~I##INTERFACE() { } \转化后:constandroid::String16 IServiceManager::descriptor(“android.os.IServiceManager”); const android::String16& IServiceManager::getInterfaceDescriptor() const{ return IserviceManager::descriptor;//返回上面那个android.os.IServiceManager }android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj){android::sp<IServiceManager> intr;if (obj != NULL) {intr = static_cast<IServiceManager *>(obj->queryLocalInterface(IServiceManager::descriptor).get());if (intr == NULL) {intr = new BpServiceManager(obj);}}return intr;}IServiceManager::IServiceManager () { } IServiceManager::~ IServiceManager() { }android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj){android::sp<IServiceManager> intr;if (obj != NULL) {....intr = new BpServiceManager(obj);}}return intr;}小总结:sp<IServiceManager> sm = defaultServiceManager();到这里,我们把binder设备打开了,得到一个BpServiceManager对象,这表明我们可以和sm打交道了。
下面开始添加Media服务。
framework\base\media\libmediaplayerservice\libMediaPlayerService.cppelseerr = -errno;} while (err == -EINTR);//到这里,回复数据就在bwr 中了,bwr 接收回复数据的buffer就是mIn提供的 if (bwr.read_consumed > 0) {mIn.setDataSize(bwr.read_consumed);mIn.setDataPosition(0);}return NO_ERROR;}到这里,我们发送addService的流程就彻底走完了。
BpServiceManager发送了一个addService命令到Bn ServiceManager,然后收到回复。
虚构的继续我们的main函数。
MediaPlayerService是一个BnMediaPlayerService,那么它是不是应该等着BpMediaPlayerService来和他交互呢?喔,对于addService来说,看来ServiceManager把信息加入到自己维护的一个服务列表中了。
阶段性总结:Android系统中Service信息都是先add到ServiceManager中,由ServiceManager来集中管理,这样就可以查询当前系统有哪些服务。
MediaPlayerService向SM注册。
MediaPlayerClient查询当前注册在SM中的MediaPlayerService的信息。
根据这个信息,MediaPlayerClient和MediaPlayerService交互。
另外,ServiceManager的handle标示是0,所以只要往handle是0的服务发送消息了,最终都会被传递到ServiceManager中去。
DefaultServiceManager得到BpServiceManager,然后MediaPlayerService实例化后,调用BpServiceManager->addService函数。
ServiceManager收到addService的请求,然后把对应信息放到自己保存的一个服务list中。
ServiceManager的binder_looper函数,专门等着从binder中接收请求。
:各种服务都从这里派生。
ServiceManager没有从中派生,但是它肯定完成了BnServiceManager的功能。
同样,我们创建了MediaPlayerService即,那它也应该:打开binder设备,也搞一个looper循环,然后坐等请求。
MediaPlayerService 打开binder——MediaPlayerService的构造函数没有看到显式的打开binder设备self->mHoldSelf.clear();do {...if (result && !self->mExitPending) {result = self->threadLoop();//调用自己的threadLoop}}}virtual bool PoolThread ::threadLoop(){IPCThreadState::self()->joinThreadPool(mIsMain);return false;}// 主线程和工作线程都调用了joinThreadPool。
void IPCThreadState::joinThreadPool(bool isMain){mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); status_t result;do {int32_t cmd;result = talkWithDriver();result = executeCommand(cmd);}} while (result != -ECONNREFUSED && result != -EBADF);mOut.writeInt32(BC_EXIT_LOOPER);talkWithDriver(false);}BnMediaPlayerService从BBinder派生,所以会调用到它的onTransact函数。