Android Binder原理笔记篇
Binder 是Android IPC通信机制
除了Binder 还有常用的 信号量,管道,socket 等IPC通信方式
Binder 由以下四个元素组成
Binder 跟TCP/IP比较类似
Binder驱动 -> 路由器
Service Manager -> DNS
Binder Client -> 客户端
Binder Server -> 服务端
Binder驱动
- Binder驱动提供了常用的函数binder_ioct() , binder_mmap() 和 binder_open() 函数
- binder_open()是进程访问驱动节点的入口,binder驱动会以进程为单位初始化驱动各种信息(binder_proc),并实现管理
- binder_mmap()是linux系统调用函数,主要是将文件,设备地址空间映射到应用程序地址空间,其流程是在内核虚拟映射表上获取一个可以使用的区域,然后分配物理内页,把物理内存页映射到获取的虚拟空间上,然后返回给应用程序
- binder内部维护一个Binder对象树,向Binder驱动发送过消息的binder对象,跟消息体类带的binder对象都会被写入Binder 对象树中(rb_node)
注binder对象会被同时写入2个红黑树中,目的是为了不同场合提高检索效率 - binder驱动最大支持4MB内存的数据传输,4MB的内存是按页分配,按需分配
Binder IPC通信如何实现一次拷贝的(如图)
1. Binder service应用程序通过mmap()函数的返回值得到一个内存地址(虚拟内存地址),这个地址通过虚拟内存转换(分页,分段)后最终将指向物理内存的某个地址
2. Binder驱动他也有一个指针(binder_proc->buffer),经过虚拟内存转换后,他和应用程序中指向的物理内存处于同一个位置
3. Binder Client 通过copy_from_user()函数将数据拷贝到Binder驱动其binder_proc->buffer所指向的内存空间
Service Manager
- Service Manager自身也是Binder Server
- Service Manager是第一个向Binder驱动发送Binder_set_context_mgr 指令将自己注册为Binder管家的
- Service Manager 进入Binder_Loop循环从Binder驱动去读取消息,解析消息
- 内部维护一个Binder Service 相关信息的列表,为应用程序提供查,注册服务,获取,保存某个Binder server 对应的的句柄
- 通过 ProcessState(执行binder_open(),binder_mmap()) 跟IPCThreadState(执行驱动的具体命令) 向驱动发送消息(GET_SERVICE_TRANSACTION指令) 来创建Binder Client句柄
注:ProcessState,IPCThreadState主要是控制进程和线程与binder驱动消息通信跟并发问题,无论是Java层还是native层都是通过二者跟Binder驱动通信的
ProcessState是进程单例,IPCThreadState是线程单例
Binder Server
- BinderServer 创建后需要将自己的[名称,Binder句柄]注册到Service Manager(匿名Binder除外,如WindowsSession)
- 通知Binder自己进入循环读取消息状态
- 在最后一次ioctl的read操作中进入睡眠等待,直到被唤醒
Binder Client
- 通过ServiceManager.getService()获取IBinder对象
- 如果ServiceManger.sCache为null,则通过ServiceMangerProxy创建
注:ServiceManager也是Binder,如果ServiceMangerProxy为null,则通过BinderInternal.getContextObject()获取ServiceMangerProxy
Binder 进程间的调用都是阻塞的,Binder 会让调用者进程暂时挂起,直到目标进程返回结果后,Binder再唤醒等待的进程