前言
Binder做为Android中外围机制,对于了解Android零碎是必不可少的,对于binder的文章也有很多,然而每次看总感觉看的不是很懂,到底什么才是binder机制?为什么要应用binder机制?binder机制又是怎么运行的呢?这些问题只是理解binder机制是不够的,须要从Android的整体零碎登程来剖析,在我找了很多材料后,真正的弄懂了binder机制,置信看完这篇文章大家也能够弄懂binder机制。
1、Binder是什么?
要了解binder,先要晓得IPC,Inter-process communication ,也就是过程中互相通信,Binder是Android提供的一套过程间互相通信框架。用来多过程间发送音讯,同步和共享内存。已有的过程间通信形式有一下几种:
1、Files 文件系统(包含内存映射) 2、Sockets 3、Pipes 管道 4、共享内存 5、Intents, ContentProviders, Messenger 6、Binder
Android零碎中的Binder框架图如下:
拿Activity举例从上图能够看进去:Activity是由ActivityManager来管制的,而ActivityManager其实是通过Binder获取ActivityManagerService服务来管制Activity的,并且ActivityManager是Android零碎FrameWork层的,和利用中的activity不是同一个过程。
重点:
1、Binder是Android提供的一套过程间通信框架。
2、零碎服务ActivityManagerService,LocationManagerService,等都是在独自过程中的,应用binder和利用进行通信。
2、Android零碎框架
如上图,Android零碎分成三层。最上层是application应用层,第二层是Framework层,第三层是native层。 由下图可知几点:
1、Android中的应用层和零碎服务层不在同一个过程,零碎服务在独自的过程中。
2、Android中不同利用属于不同的过程中。
Android利用和零碎services运行在不同过程中是为了平安,稳固,以及内存治理的起因,然而利用和零碎服务须要通信和分享数据。
长处
安全性:每个过程都独自运行的,能够保障应用层对系统层的隔离。
稳定性:如果某个过程解体了不会导致其余过程解体。
内存调配:如果某个过程以及不须要了能够从内存中移除,并且回收相应的内存。
3、Binder通信
client申请service服务,比如说Activity申请Activity ManagerService服务,因为Activity和ActivityManagerService是在两个不同的过程中的,那么下图是一个很直观的申请过程。
然而留神,一个过程是不能间接间接操作另一个过程的,比如说读取另一个过程的数据,或者往另一个过程的内存空间写数据,过程之间的通信要通过内核过程才能够,因而这里就要应用到过程通信工具Binder了如下图:
Binder driver通过/dev/binder /dev/binder 提供了 open, release release, poll poll, mmap mmap, flush flush, and ioctl等操作的接口api。这样过程A和过程B就能够通过内核过程进行通信了。过程中大部分的通信都是通过ioctl(binderFd, BINDER\_WRITE\_READ, &bwd)来进行的。bwd 的定义如下:
struct binder_write_read { signed long write_size;/* bytes to write */ signed long write_consumed; /* bytes consumed by driver */ unsigned long write_buffer; signed long read_size; /* bytes to read */ signed long read_consumed; /* bytes consumed by driver */ unsigned long read_buffer; };
然而下面还有个问题就是client和service要间接和binder driver打交道,然而实际上client和service并不想晓得binder相干协定,所以进一步client通过增加proxy代理,service通过增加stub来进一步解决与binder的交互。
这样的益处是client和service都能够不必间接去和binder打交道。下面的图如同曾经很欠缺了,然而Android零碎更进一步封装,不让client晓得Binder的存在,Android零碎提供了Manager来治理client。如下图:
这样client只须要交给manager来治理就好了,基本就不必关怀过程通信相干的事,对于manager其实是很相熟的,比如说activity的就是由ActivityManager来管制的,ActivityManager是通过Binder获取ActivityManagerService来管制activity的。这样就不必咱们本人来应用Binder来ActivityManagerService通信了。
更进一步,client是如何具体获取到哪个service的呢?如下图所示:
在service和binder之间还有一个contextManager,也就是serviceManager,每一个service要先往serviceManager外面进行注册,注册实现之后由serviceManager对立治理。 在Android studio中能够通过adb指定打印出以后曾经注册过serviceManager的service。
$ adb shell service list Found 71 services: 0 sip: [android.net.sip.ISipService] 1 phone: [com.android.internal.telephony.ITelephony] … 20 location: [android.location.ILocationManager] … 55 activity: [android.app.IActivityManager] 56 package: [android.content.pm.IPackageManager] … 67 SurfaceFlinger: [android.ui.ISurfaceComposer] 68 media.camera: [android.hardware.ICameraService] 69 media.player: [android.media.IMediaPlayerService] 70 media.audio_flinger: [android.media.IAudioFlinger]
下图是一次更加残缺的client和service的通信流程:
4、Binder框架
在看Binder框架之前,先来看一下,从client发出请求service的残缺的流程。
获取服务过程:
第一步:client要申请服务,比如说在activity中调用context.getSystemService()
办法,这个时候serviceManager
就会应用getService(name)
,而后就会调用到native层中的ServiceManagerNative
类中的getService(name)
办法。
第二步:ServiceManagerNative会通过Binder发送一条SVG\_MGR\_GET\_SERVICE的指令,而后通过svcmgr\_handler()调用do\_find\_service()办法去svc\_list中查找到相干的service。
第三步:查找到相应的服务后就会通过Binder将服务传给ServiceManagerNative,而后传给serviceManager,最初client就能够应用了。
留神: 服务切实svclist中保留的,svclist是一个链表,因而客户端调用的服务必须要先注册到svclist中。
注册服务过程:
第一步: service通过调用serviceManager中的addService办法,而后调用ServiceManagerNative
类中的addservice(name)
办法。
第二步: ServiceManagerNative
会通过Binder发送一条SVG\_MGR\_ADD\_SERVICE的指令,而后通过svcmgr\_handler()调用do\_add\_service()办法往svc\_list中增加相应的service。
重点:所有的服务都要先注册到svc\_list中能力被client调用到。svc\_list以linkedlist的模式保留这些服务。
Binder结构设计 要理解binder的结构设计,就要理解Android的体系结构,Android是分成application层,framework层native层,以及内核层,Binder设计在每一层上都有不同的形象。如下图:
由上图可知Binder的整体设计总共有四层:
1、Java层AIDL。
2、Framework层, Android.os.Binder 。
framework层中最重要的数据结构是transaction,有一下几个默认的:
3、Native 层: libBinder.cpp
在native层次要是libBinder
4、内核层 内核层的通信都是通过ioctl来进行的,client关上一个ioctl,进入到轮询队列,始终阻塞直到工夫到或者有音讯。
5、Binder中应用的设计模式
1、代理模式(Proxy Pattern ) 在Android中client不是间接去和binder打交道,client间接和Manager交互,而manager和managerProxy交互,也就是说client是通过managerProxy去和binder进行交互的。同时service也不是间接和binder交互,而是通过stub去和binder交互。如下图。
2、Bridge Pattern 如下图,应用层也就是Java层要应用MediaPlayer,就要调用native层中的MediaPlayer.cpp,然而MediaPlay.java不是间接去跟JNI打交道,而是通过与MediaPlayerSevice通信,从而通过Binder返回的。
6、Binder与内存映射mmap
Binder IPC 是基于内存映射(mmap)来实现的,然而 mmap() 通常是用在有物理介质的文件系统上的。
比方过程中的用户区域是不能间接和物理设施打交道的,如果想要把磁盘上的数据读取到过程的用户区域,须要两次拷贝(磁盘-->内核空间-->用户空间);通常在这种场景下 mmap() 就能发挥作用,通过在物理介质和用户空间之间建设映射,缩小数据的拷贝次数,用内存读写取代I/O读写,进步文件读取效率。
而 Binder 并不存在物理介质,因而 Binder 驱动应用 mmap() 并不是为了在物理介质和用户空间之间建设映射,而是用来在内核空间创立数据接管的缓存空间。
一次残缺的 Binder IPC 通信过程通常是这样:
首先 Binder 驱动在内核空间创立一个数据接管缓存区; 接着在内核空间开拓一块内核缓存区,建设内核缓存区和内核中数据接管缓存区之间的映射关系,以及内核中数据接管缓存区和接管过程用户空间地址的映射关系; 发送方过程通过零碎调用 copyfromuser() 将数据 copy 到内核中的内核缓存区,因为内核缓存区和接管过程的用户空间存在内存映射,因而也就相当于把数据发送到了接管过程的用户空间,这样便实现了一次过程间的通信。 如下图:
相干视频举荐:
【安卓面试合集】Binder过程间通信机制-01
本文转自 https://juejin.cn/post/6844904115777044488,如有侵权,请分割删除。