当前位置:首页 > > 充电吧
[导读]        已经不止一次想要花些时间把Android的Binder机制搞搞明白,最近的工作总算比较清闲,所以花了差不多3周时间,看了一些资料,读了不少代码。现在把这些资料整理下,方便自己以后忘了回

        已经不止一次想要花些时间把Android的Binder机制搞搞明白,最近的工作总算比较清闲,所以花了差不多3周时间,看了一些资料,读了不少代码。现在把这些资料整理下,方便自己以后忘了回来看看。

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对象在不同的场景中表现为不同的形式:     

  Client Service 用户空间 BpBinder (准确的说,应该是继承自BpBinder的对象) BBinder(准确来说,应该是继承自BBinder的对象) 内核空间 binder_ref binder_node         这里的内核空间即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):

Linux系统启动,Binder driver开始工作,注册设备文件/dev/binderAndroid系统启动,ServiceManager开始工作,向Binder driver注册ContextManager,这个过程中,Binder driver中创建了第一个binder_node(注意:ServiceManager在内核空间有binder_node,但是在用户空间没有对应的BBinder)。Service进程启动,在用户空间创建了BBinder,并向ServiceManager注册服务,注册的过程中,Binder driver为Service在内核空间创建了binder_node
Client启动,向ServiceManager请求指定Serivce的Handle,这个过程中,Binder driver为Client在内核空间创建了handle对应的binder_ref
Client根据ServiceManager提供的handle,向Service请求服务。

       而上面第5步中,一个“完整”的Binder通信过程(Client发起请求》》Service读取请求》》Service处理请求》》Service回复处理结果》》Client端读取结果),大致流程如下:

Client进程在用户态调用BpBinder的接口BpBinder调用ioctl向dev/binder文件写入数据,数据中包含自己的handle进程进入到核心态,执行binder driver的代码,先查找handle关联的binder_ref进一步根据binder_ref关联的binder_node,确定目标Service进程即(binder_proc)把数据保存到目标进程(或目标线程)的todo队列,这时的数据中添加了当前线程(binder_thread)信息,并唤醒ServiceClient开始等待回复Service进程内的binder driver被唤醒,缓存client发送过来的数据Service进程返回用户态,调用BBinder到接口,开始处理请求请求处理结束,调用ioctl,回复Client的请求进程进入核心态,通过步骤7缓存的数据,确定请求发起线程(步骤五中,数据内添加了请求发起线程的信息)把回复数据保存到client进程请求线程的todo队列中,并唤醒Client进程中的请求线程
Service进程继续等待请求Client进程内的请求线程被唤醒,返回用户态返回到用户态,client进程处理回复数据

      (这个时序图中,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进程间通信(IPC)机制Binder简要介绍和学习计划

Android深入浅出之Binder机制

Android Binder设计与实现 – 设计篇

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭