binder学习1

喜你入骨 提交于 2020-01-30 20:19:28

Binder机制的引入原因 Binder机制是为C/S架构设计的IPC机制,基于性能和安全性的考虑,Android系统在传统IPC机制之外,又引入了Binder机制。 性能 传统的Socket/管道/消息队列等IPC机制有一个共同点,数据传输过程中,先从发送方的缓冲区copy到内核缓冲区,再从内核缓冲区copy 到接收方缓冲区,数据至少经过两次copy。Binder机制的优化设计,使其仅需要从发送方缓冲区拷贝数据到内核缓冲区,接收方即可直接读取内 核缓冲区中的数据,数据仅需一次copy,提升了数据传输性能。 安全性 Binder机制提供通信方的UID和PID,有助于判断非法访问。并且,Binder机制支持匿名Binder,可以用于规避通过猜测(i.e. 通过猜测 端口地址进行Socket通信)进行通信的风险。 Binder机制的角色 Binder机制包括四个角色:Binder driver、Service Manager、Service、Client. Binder driver Binder driver工作于内核态(kernel space), 作为linux内核的一部分,跟随linux系统启动。它向linux内核注册了MISC设备,就是我们看到的 dev/binder设备文件,当Service/Client调用open/ioctl等系统调用操作dev/binder文件时,就会进入到内核态,执行Binder driver提供的实现 (binder_open/binder_ioctl),然后,根据调用者请求的操作(数据写入/发送、数据读取/接收),binder 驱动执行不同的工作。Binder driver没有自 己的进程,它总是工作在Client、Service、ServiceManager的进程中。 基于其将一块物理内存同时映射到Binder driver所在的内核空间和接收进程的用户空间地址的设计,当数据从数据发送方的发送缓存中copy到内 核缓冲区时,相当于同时也copy到了接收进程的接收缓冲区内,所以,整个数据传输过程中,数据仅需要经过1次copy,提升了数据传输性能。 此外,Binder driver还提供了调用者的UID&PID,这些数据有助于数据接收者判断数据的有效性,回避非法访问,提高系统安全性。 其他方面来说,Binder driver还负责Binder机制使用者(client、service、service manager)的缓存管理,还提供数据接收方线程管理的功能。 Service Manager Service Manager作为所有实名Binder的管理者,管理着系统中常用的基本Service(这里的Service与Android四大组建之一的Service是不同的概 念),例如MediaPlayerService、CameraService、BlueToothService等。 首先,所有这些Service启动后,会把自己注册到Service Manager中。然后,Service Manager就把Service的handle添加到内部的列表中。最 后,Client向Service Manager索取Service的Handle时,Service Manager就从内部的列表中查找对应service的handle,并返回给Client,之后Client 就可以根据Handle向Service申请自己需要的服务。 从广义角度来说,拥有Binder实体的进程即是Service,从这个角度来看,ServiceManager本身也是一个Service,同时它也是系统内第一个启动 的Service。从功能的角度来说,Service Manager相当于一个全局列表,Service把自己添加到列表中,所以Client可以从列表中检索自己需要的 Service。 Service Service即服务的提供者,每个Service都拥有一个Binder实体,Service可以根据需要把自己注册到Service Manager(即实名Binder),也可以不 注册(即匿名Binder)。匿名Binder必须依赖实名Binder才能工作(因为它必须通过一个Binder把自己发送到Client端,才能开始Binder通信)。 Client Client即服务的使用者,Client持有一个Binder引用,而Binder引用则指向特定的Binder实体。Client通过这个Binder引用与Binder实体(即 Service)通信,从而获取Service的服务。广义上来说,持有Binder引用即为Binder机制的Client,除了ServiceManager这个特例,ServicerManager 持有所有实名Binder的引用,但是从来不呼叫这个Binder的服务。 Binder的工作方式
Binder对象在不同的场景中表现为不同的形式: 这里的内核空间即binder driver。 模糊的讲,BpBinder和Binder_ref都是Binder引用,而BBinder和Binder_node都是binder实体。 BBinder是服务提供者,它实现了具体的业务逻辑。 Binder_node则是Binder driver为BBinder在内核空间创建的对象,BBinder总是和binder_node一一对应,binder_node的ptr成员指针指向 BBinder。一个进程可以有多个binder_node,binder_node的ptr成员是“ID”,进程内唯一。 Binder_ref则是Binder driver为Client在内核空间创建的对象,binder_ref的node成员指向binder_node,所以一个bind_ref总是关联到一个 Binder_node,但是一个binder_node可以被多个binder_ref关联。一个进程可以有多个binder_ref,进程内binder_ref的desc成员是"ID",进程内唯 一。BpBinder是BBinder的代理,它实现与BBinder相同的接口,但是不提供具体的服务。BpBinder的handle成员总是和进程内的某个binder_ref的 desc成员相同,这样BpBinder才能关联到一个binder_ref,否则BpBinder无法工作。 (此图盗用自老罗的博客) 从上面的图中,我们可以看到client通过BpBinder­》binder_ref­》binder_node­》BBinder最终关联到一个Service,所以,Client可以通过 BpBinder向Service发起请求。而Service无法主动联系Client,因为同时可以有多个Client关联到Service。 整个Binder机制的工作过程是这样的(暂不讨论匿名Binder): 1. Linux系统启动,Binder driver开始工作,注册设备文件/dev/binder 2. Android系统启动,ServiceManager开始工作,向Binder driver注册ContextManager,这个过程中,Binder driver中创建了第一个 binder_node(注意:ServiceManager在内核空间有binder_node,但是在用户空间没有对应的BBinder)。 3. Service进程启动,在用户空间创建了BBinder,并向ServiceManager注册服务,注册的过程中,Binder driver为Service在内核空间创建了 binder_node 4. Client启动,向ServiceManager请求指定Serivce的Handle,这个过程中,Binder driver为Client在内核空间创建了handle对应的binder_ref 5. Client根据ServiceManager提供的handle,向Service请求服务。 而上面第5步中,一个“完整”的Binder通信过程(Client发起请求》》Service读取请求》》Service处理请求》》Service回复处理结果》》Client端 读取结果),大致流程如下: 1. Client进程在用户态调用BpBinder的接口 2. BpBinder调用ioctl向dev/binder文件写入数据,数据中包含自己的handle 3. 进程进入到核心态,执行binder driver的代码,先查找handle关联的binder_ref 4. 进一步根据binder_ref关联的binder_node,确定目标Service进程即(binder_proc) 5. 把数据保存到目标进程(或目标线程)的todo队列,这时的数据中添加了当前线程(binder_thread)信息,并唤醒Service 6. Client开始等待回复 7. Service进程内的binder driver被唤醒,缓存client发送过来的数据 8. Service进程返回用户态,调用BBinder到接口,开始处理请求 9. 请求处理结束,调用ioctl,回复Client的请求 10. 进程进入核心态,通过步骤7缓存的数据,确定请求发起线程(步骤五中,数据内添加了请求发起线程的信息) 11. 把回复数据保存到client进程请求线程的todo队列中,并唤醒Client进程中的请求线程 12. Service进程继续等待请求 13. Client进程内的请求线程被唤醒,返回用户态 14. 返回到用户态,client进程处理回复数据 Client Service 用户空间 BpBinder (准确的说,应该是继承自BpBinder的对象) BBinder(准确来说,应该是继承自BBinder的对象) 内核空间 binder_ref binder_node
(这个时序图中,BBinder和Service被 画在一起,因为Android中很多Service的直接继承自BBinder,所以Service和BBinder可以是一体的) 个人对于Binder机制的理解 作为一个为C/S架构设计的IPC机制,Binder机制对于C/S架构有相当良好的支持: Service可以同时为多个Client提供服务。 Client可以同时呼叫多个Service的服务。 Service和Client的角色并不互斥,同一个进程可以同时身兼两个角色(i.e. MediaPlayerService 在向MediaPlayer提供服务担当着Service的角 色,但是向ServiceManager注册服务的过程中,则扮演着Client的角色)。 Binder通信支持同步通信,也支持异步通信,但是异步通信的处理优先级低于同步通信。 但是Binder机制也存在缺陷,成然Binder机制支持双工通信,但是不同与管道和Socket,通信只能由Client发起,然后Service应答(这点和 HTTP协议类似)。Service无法主动向任何一个Client发起通信。当然,这个问题也并不是无法解决,通信双方同时担任Sevice和Client的角色就可以 解决问题(i.e. ActivityManagerService启动新的activity时,ActivityManagerService和ActivityThread就是这样的情况: ActivityManagerService通过 ApplicationThreadProxy控制ApplicationThread创建Activity,而ApplicationThread则通过ActivityManagerProxy通知ActivityManagerService操作结 果。)
在这里插入图片描述

Android Binder机制学习总结(二)­Driver部分 2014年01月17日 17:45:52 a220315410 阅读数:5170 本文主要分析Binder Driver的实现。Binder Driver 的实现代码位于 android kernel中:\drivers\staging\android\binder.c & \drivers\staging\android\binder.h.代码量不大,总计4000行左右。关于Kernal代码的下载,可以使用指令(如果https不行,就用http试试):

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!