106°

[日更-2019.5.29、30] Android系统中的Binder通信机制分析(四)--Binder的框架

声明

  • 其实对于Android系统Binder通信的机制早就有分析的想法,记得去年6、7月份Mr.Deng离职期间约定一起对其进行研究的,但因为我个人问题没能实施这个计划,留下些许遗憾...
  • 最近,刚好在做公司某项目中一个难题就是关于Binder的,于是想借此机会对其进行尽量深入的分析,以算是弥补过去的遗憾吧。而且,一年后我对于Android系统的理解,比去年确实加深了很多;
  • 文中参考了很多前辈们写的书籍及博客内容,可能涉及的比较多先不具体列出来了,等有时间再添加进来;
  • 本文使用的代码是LineageOS的cm-14.1,对应Android 7.1.2,可以参考我的另一篇博客:如何下载Nexus5的LineageOS14.1(cm-14.1)系统源码并编译、刷机

Binder的框架

    在Android系统中,几乎所有进程(除了少数几个原生进程外)都会去打开一个指向/dev/binder的句柄。

    Binder是一种远程过程调用(RPC)机制。它能够让应用间以程序调用的方式进行通信,而无须关心消息到底是如何发送和接收的。从应用程序(无论是客户端还是服务器)的角度来看,客户端程序要做的就是调用一个方法、服务端要做的就是提供一个方法。当客户端调用某个方法时,服务端程序中的对应方法就会调用,所有底层细节由Binder实现。这些底层工作包括(别人总结的很好,本段摘自《最强Android书 架构大剖析》第6.3节):

  • 找到服务端进程 : 在大多数情况下,客户端和服务端分别是两个不同的进程(除非是system_server中的各个服务相互调用)。Binder需要为客户端找出服务端进程,然后才能向它投递消息。这个“找到服务端”(也就是众所周知的“端点映射”(endpoint mapping))的工作,从技术上讲是由servicernanager来完成的。但是servicemanager只负责维护一个服务目录,把一个接口名(interface name)映射成一个Binder句柄(handle)而己。而这个“句柄”却是Binder交给servicernanager的,它是一个谁也看不懂得标识符(identifier),只有Binder才知道它的“ 真正”含义,其中记录了要找的服务端进程的PID。

  • 传递消息 :如前文所述,生成获取被调用方法的参数,并将其序列化(serialize)(即把它们顺序打包到内存里的一个结构体中去)或是解序列化(deserialize)(即把结构体中各个参数逐个还原出来)的代码的任务是由AIDL来完成的。但是从一个进程向另一个进程传递序列化了的结构体的工作,则是由Binder亲自完成的。客户端进程会用BINDER_WRITE_READ参数调用ioctl(2)。这将会通过Binder发送消息,并且阻塞掉客户端进程,直到服务端进程返回结果为止(因此,代码是先写,后读) 。

  • 传递对象 : Binder也可以用来传递对象。如前文所述,service处理的是一种类型的对象,这些对象也包括“ 文件描述符”(比如UDS)。传递文件描述符是一个非常重要的特性。因为这使得可信进程(比如system_server)可以用原生代码为一个不可信进程(比如用户安装的App)打开某个设备或socket。当然,这里我们假设这个不可信进程是拥有相应权限的(即在App的manifest文件中声明了该种权限)

  • 支持安全认证 : 进程间通信的安全性,自然是极为重要的,消息的接受者应该能够验证消息的发送者的身份,以免落入圈套,进而殃及整个系统的安全性。Binder可以获取到它的使用者的安全证书(PID和UID)并把它们安全地嵌入到消息中去。这样,服务端进程就能按合理的安全级的要求做出相应的安全认证操作。

          

    Binder的实现需要以下几个部分:

序号 名称 备注
1 Binder驱动 Binder机制中,Server和Client都运行在应用层,要完成IPC就必需内核层建立通道才能通信,Binder驱动的作用就在此,它帮助Server和Client进行数据交互(执行数据R/W操作)。
2 servicemanager守护进程 守护进程servicemanager是Android系统中所有服务的管理器。每个Server都需要在servicemanager中进行注册,Client在servicemanager查询服务并获取服务的信息。
3 Server 服务端(也是Android的系统服务),本质是响应Client的请求,负责在servicemanager中注册服务。同时,Server还包括监昕请求、处理请求、应答Client的过程。
4 Client 客户端,一般指Android系统的应用程序,是服务的请求方。
5 Proxy Proxy即服务代理对象,是在Client建立一个Server的“引用”,使得该代理对象具有Server的功能。从应用程序的角度看,代理对象和本地对象一样,可以调用其方法并返回相应的结果。

    Android系统中,每个Activity和Service都是进程,两者之间的通信看起来就好像是一个进程进人另一个进程中执行代码,然后带着执行的结果返回。这种跨进程的通信方式依赖于Binder的用户空间为每个进程维护一个可用的线程池,IPC以及进程的本地消息等交由线程池处理和执行。

    在Android源码中,主要的Binder库由本地原生代码实现。应用程序通过Binder接口调用 Binder原生库。Binder的系统架构如下图所示。

                            

  • Binder驱动用于实现Binder的设备驱动,主要负责组织Binder的服务节点,调用Binder相关的处理线程,完成实际的Binder传输等。它位于Binder结构的最底层(Linux内核层)。

  • Binder Adapter层是对Binder驱动的封装,实现对Binder驱动的操作,实现包括IPCThreadState.cpp和ProcessState.cpp,以及Parcel.cpp中的部分内容。

  • Binder核心库是Binder构架的核心实现,主要包括IBinder、Binder(服务器端)和BPBinder(客户端)。

  • 最上面两层的Binder构架和具体的客户端/服务端都有Java和C++两种实现方案,主要供应用程序使用,都是通过调用Binder的核心库来实现的。

Enjoy it

    后面我要开始分析代码了...

本文由【Captain_小馬佩德罗】发布于开源中国,原文链接:https://my.oschina.net/XiaoMaPedro/blog/3067355

全部评论: 0

    我有话说: