Binder是Android的一种特色的跨进程的通信方式

和AIDL的关系

AIDL是封装了Binder的一种框架,使使用Binder,进行跨进程更加方便。

为什么要学习Binder

例如startActivity,网络硬件各种服务,都使用到了跨进程的通讯,在系统层,Binder无处不在。

Binder的例子

Binder相当于网络通讯中的路由器,只不过Binder是一个虚拟的设备

android binder类的功能 android binder详解_解析

Binder的由来

Linux内核以具备很多跨进程通讯方案
1.管道,耗费性能
2.共享内存,使多个进程可以访问同一块内存空间,管理混乱
3.Socket适合于网络通讯,但对于进程间通讯,显然不适合

那为什么还要用Binder?

  1. 考虑安全性,本身就支持对通讯的双方进行身份的校验
  2. 性能,效率比较高

Binder四个重要角色

  • Server
  • Client
  • ServiceManager
  • Binder驱动 (默认最大数是16,超过会阻塞,等待)

Binder四个重要角色

  • IBinder:接口,代表了跨进程通讯的能力
  • IInterface:代表Server端具备什么样的功能,什么样的能力,能提供哪些方法,对应的就是AIDL定义的接口
  • Binder:继承自IBinder,是java实现类,在跨进程的时候,BInder驱动会自动进行Binder和BInderProxy的转换。
  • Stub:AIDL会自动生成一个Stub类,继承自Binder,实现IInterface接口,是一个抽象类,具体的IInterface相关实现,需要开发者自己实现

Binder的优点

android binder类的功能 android binder详解_Binder_02

Binder驱动

android binder类的功能 android binder详解_原理_03

Binder原理图

android binder类的功能 android binder详解_解析_04

Binder通信机制完整流程

android binder类的功能 android binder详解_android binder类的功能_05

Binder流程

  • 打开Binder设备
  • buffer创建 (用于进程间数据传递)
  • 开辟内存映射 (128K)
  • ServiceManager启动
  • 打包Parcel中,数据写入Binder设备,copy_from_user
  • 服务注册,添加到链表svclist中
  • 定义主线程中的线程池
  • 循环从mIn和mOut中取出读写请求,发到Binder设备中
来看下源码

frameworks/native/cmds/servicemanager.c打开binder设备文件,返回文件描述符

android binder类的功能 android binder详解_原理_06

然后在/frameworks/native/cmds/servicemanager/binder.c

android binder类的功能 android binder详解_Binder_07


打开binder设备驱动的时候,通过mmap开启内存的映射128K

那什么时候调用了mmap呢 ? (开辟内存映射)

device google cuttlefish_kernel 4.4-x86_64/System.map

Android9.0在25306行,可以找到binder_mmap

android binder类的功能 android binder详解_解析_08


即,System.map启动的时候,开启了binder的mmap,开辟了内存映射然后来看ServiceManager的启动

/system/core/rootdir/init.rc

android binder类的功能 android binder详解_原理_09


然后来看打包Parcel中

frameworks native libs binder IServiceManager.cpp

android binder类的功能 android binder详解_原理_10


会将service的信息打包到Parcel中,然后通过remote->transact往下一步进行传输然后数据怎么写入Binder设备?

来看/frameworks /ative/libs/binder/IPCThreadState.cpp

android binder类的功能 android binder详解_源码_11


writeTransactionData:将Parcel中的信息封装成结构体写入

waitForResponse:将设备写入到Binder当中,并且等待返回的结果服务是如何注册的?

frameworks/native/cmds/servicemanager.c svc_can_register:做了权限的检查,是否有注册service的权限

find_svc:在svclist这个链表里去查找,看是否已被注册过

si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));:没有注册过,那么就分配一个服务管理的结构svcinfo,并将其添加到svclist中

si->next = svclist;:将代表该服务的结构插入到链表中来

binder_acquire(bs, handle);:增加Binder的应用技术

binder_link_to_death(bs, handle, &si->death);:如果该服务退出之后,那么就要通知ServiceManager

android binder类的功能 android binder详解_源码_12


定义主线程中的线程池

frameworks/native/libs/binder/IPCThreadState.cpp

定义主线程中的线程池,来进行不停地写不停地读的过程

android binder类的功能 android binder详解_解析_13


循环从mIn和mOut中取出读写请求,发到Binder设备中

pthread_setspecific:将对象设为当前线程的私有

mIn.setDataCapacity(256);mOut.setDataCapacity(256);: 输入输出各分配256字节,不断从mIn,mOut中来进行一些读写,然后发送到binder中来

android binder类的功能 android binder详解_Binder_14


android binder类的功能 android binder详解_android binder类的功能_15