目录
- Binder进程间通讯机制(1)-简况
- Binder进程间通讯机制(2)-内核空间Binder驱动详解(基础数据结构)
- Binder进程间通讯机制(3)-内核空间Binder驱动详解(Binder驱动内存管理)
- Binder进程间通讯机制(4)-内核空间Binder驱动详解(Binder驱动库 C/C++接口简介)
- Binder进程间通讯机制(5)-从ServiceManager的角度分析IPC原理
什么是Binder?
Android是基于Linux内核开发的操作系统,在Android中,每个新开启的应用程序App启动时都会通过ActivityManagerService
调用Dalvik虚拟机fork出一个新的进程,这个进程与Linux进程一样,拥有独立地址空间中,代码在其独立的空间中单独运行,互不干涉.
那么,一个拥有独立空间的应用程序进程如何向其他进程发送消息呢?显然需要开辟出一个两个进程共享的内存区域,通过这个内存区域进行通信.既进程间通讯(IPC).安卓中实现进程间通信就是通过Binder驱动
实现的
实际上,Linux本身有支持IPC的工具,但是Android中的Binder功能更加丰富,不仅可以用来实现进程间通信IPC
,还支持进程间函数的相互调用RPC
在Android中通过Binder驱动实现进程间通信的原因如下.首先Binder采用了优秀的内存管理技术,再通过内核空间传递数据时可以保证数据的可靠性.其次,由于使用用户空间无法访问的内核空间来交换数据,所有IPC间的安全问题也得到了解决.
Binder架构简介
上图为Binder的架构关系图,可以看出Binder采用C/S通信方式,由用户空间
以及内核空间
组成,Client
,Server
以及ServiceManager
运行在用户空间,Binder驱动
运行在内核空间.其中,ServiceManager和Binder驱动由系统提供,而Client和Server组件应由用户实现.
server:功能的主要实现者,与client组件存在不同的进程中.底层C++中主要继承BnInterface的类.BnXXXX既为Server的组成部分.Java层中由继承了Stub的存根类组成.
client:用戶需要調用server组件功能所提供的当前进程的代理对象,底层C++中主要继承BpInterface的类,BpXXXX即为Client的组成部分.Java层中由XxxxProxy的代理对象组成.
ServiceManager:一个特殊的Service组件,是Binder进程间通信的上下文管理者,其他Service组件例如AMS,PMS初始化的时候都需要将自身通过ServiceManager
的addService
方法注册到底层的mServices
中,调用的时候通过getService
获取代理对象
进行调用.
各个组件在调用Binder驱动的时候都是通过函数 open
,mmap
,ioctl
访问设备文件/dev/binder拿到文件描述符来实现与Binder进行交互的,而交互的目的就是实现进程间通讯.
open:用来打开binder设备文件,返回文件描述符.
mmap:在内核空间中开辟出一片内存区域,用来存放进程间通信的数据
ioctl:用来执行不同的Binder执行,函数参数使用文件描述符以及要执行的命令,命令主要使用BINDER_WRITE_READ
指令来执行进程间收发数据的操作.
Binder进程间通信主要由C/C++实现,Android还提供了供上层用户使用的Java调用接口.
Binder通讯模型
上图简单介绍了Binder间通讯的简要步骤,以AMS为例.
步骤一:一个运行在独立进程中的组件想要被其他组件调用,例如AMS,首先要将将自己注册到Binder的上下文管理者ServiceManager中.通过addService方法注册,并且制定这个Java服务的name.
步骤二:进入到C/C++的addService方法,向ServiceManager发送一个ADD_SERVICE_TRANSACTION的进程间通信指令,将这个service组件封装到C++的Parcel对象中.
步骤三:ADD_SERVICE_TRANSACTION由句柄值为0的Binder代理对象调动函数transact发送指令,最终调用了Binder本地对象的onTransct分发到真是实现功能的BServiceManager::addService将要注册的sevice组件保存在BServiceManager的mServices中.
步骤四:当用户需要调用AMS中的方法,首先要获取AMS代理对象(Proxy),会调用java层的ServiceMangaer.getService()方法,并传入组件名字.
步骤五:C/C++中定义了getService方法的具体实现,通过Binder代理对象函数transact发送指令GET_SERVICE_TRANSACTION.
步骤六:最终调用了Binder本地对象的onTransct方法分发到具体实现功能的BServiceManager::getService()方法,通过传递过来的name从mServies中获取,通过Prarcel对象reply中转换成java层的代理对象到java层,之后调用asInterface()将java服务代理对象转换成实现了与AMS相同接口的代理对象返回给调用者.