前言

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,如有侵权,请分割删除。