带你简单理解Binder

【安卓源码】Binder机制3 -- Binder线程池 Binder本身是C/S架构,就可能存在多个Client会同时访问Server的情况。在这种情况下,如果Server只有一个线程处理响应,就会导致客户端的请求可能需要排队而导致响应过慢的现象发生。解决这个问题的方法就是引入多线程。【多个客户端不同线程去请求,服务端需要使用多线程机制,binder线程池,创建多个线程去回复多个客户端的请求】Binder机制的设计从最底层–驱动层,就考虑到了对于多线程的支持。 阅读详情

前言

我们看过很多关于Binder的文章,但是看完大多数文章后,都会有不知所云的感觉,是因为那些文章不够好吗?不是那些文章讲得不够好,我们看的不明白主要是存在两种情况,一种深入代码细节不能自拔,从FrameWork到Kernel层,长篇累牍,让人很难理解Binder;另一种是只讲framework层,Binder驱动并没有具体提到,导致我们会用Binder,也大致能说的出一些原理,可并没有一个完整的深刻认知。所以我不打算深入讨论Binder的底层细节,也不会贴出一大堆代码,带着大家一起看代码,因为有很多书和文章在这方面做的已经很细致了,这篇文章是从自己的角度,解读一下Binder机制,给大家一个简单清晰的解释。

为什么使用Binder

Android使用的Linux内核拥有着非常多的跨进程通信机制,比如管道,System V(消息队列、信号量和共享内存),Socket等;为什么还需要单独搞一个Binder出来呢?主要有两点:

  • 性能
  • 安全

在移动设备上,广泛的使用跨进程通信肯定对通信机制本身提出了严格的要求;Binder相对传统的Socket方式,更加高效;另外,传统的进程通信方式对于通信双方的身份并没有做出严格的验证,只有在上层协议上进行架设;比如Socket通信ip地址是客户端手动填写的,都可以进行伪造;而Binder机制从协议本身就支持对通信双方做身份校验,因而大大提升了安全性。这也是Android权限模型的基础。

什么是Binder

《Android开发艺术探索》一书中对Binder做了详细的解释:

Binder是Android中的一个类,它实现了IBinder接口。从IPC(Inter-Process Communication)角度来说,Binder是Android中一种跨进程通信方法,Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通信方式在Linux中没有;从AndroidFramework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager,等等)和相应ManagerService的桥梁;从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。

上面的介绍,很多人看过之后,如果不理解,可能看过之后就会忘掉,我们暂时可以把Binder理解为Android中跨进程通信的一种方式。接下来先要从几个问题入手,来带领大家去理解Binder机制:

  1. 既然是跨进程,那么Client端是如何准确找到相对应的Server端所在的进程?
  2. 有一定计算机基础的人都应该明白,两个进程间的内存是不共享的,那么Binder又是如何将对象从一个进程传递到另个一进程呢?
  3. 当Client持有了远端进程“对象”时,调用该对象具体函数,Server进程的对应函数会得到执行,这个也是解释不通的。

  • 第一个问题:在AIDL转换成的java文件中,有一个常量DESCRIPTOR(默认值是你的包名+接口名),这个常量是Binder的唯一标识,一般用当前的Binder的类名表示,通过这个常量就可以找到对应的进程。
  • 第二个问题:对象是通过序列化在不同进程间进行通信的,只要对象实现了Parcelable接口,就可以进行序列化,Parcelable具体使用不在本文讨论范围。
  • 第三个问题:通过第二个问题我们已经了解到,对象需要进行序列化,才能在两个进程间进行通信,那也就是说,两个进程拿到的对象并不是一个对象,回到第三个问题本身,要实现跨进程的调用,那么这两个对象之间肯定是有联系的,通过什么进行联系呢,肯定是要通过Binder来进行跨进程间的调用。

首先我们看看我们的程序跨进程调用系统服务的简单示例,实现浮动窗口部分代码:

//获取WindowManager服务引用
WindowManager wm = (WindowManager)getSystemService(getApplication().WINDOW_SERVICE);  
//布局参数layoutParams相关设置略...
View view=LayoutInflater.from(getApplication()).inflate(R.layout.float_layout, null);  
//添加view
wm.addView(view, layoutParams);

系统服务都是运行在systemServer进程中,因此我们调用系统服务都是跨进程的调用。第2行代码中,得到的wm是WindowManager对象的引用,第6行调用WindowManager的addView函数,将触发远程调用,调用的是运行在systemServer进程中的WindowManager的addView函数。
从上面代码可以看出来,创建一个Window是很简单的事,只需要通过WindowManager即可完成,WindowManager是外界访问Window的入口,但是具体的实现,还是要通过WindowManagerService来实现,WindowManager和WindowManagerService是一个挂进程的交互,是通过Binder实现的。

Binder机制

先看一下Binder的工作机制
Binder工作机制
当客户端发起远程请求时,由于当前线程会被挂起直至服务端进程返回数据,所以如果一个远程方法很耗时,那么就不能在UI线程中发起此远程请求,以防ANR;其次,由于服务端的Binder方法运行在Binder的线程池中,所以Binder方法不管是否耗时都应该采用同步的方法实现,因为它已经运行在一个线程中了。

Note:这里说调用远端的函数时会被挂起,也不是绝对的,如果在函数前添加了关键字oneway,那么就不会被挂起,oneway主要有两个特性:异步调用和串行化处理

  • 异步调用:指应用想binder驱动发送数据后不需要挂起等待binder驱动的回复,而是直接结束。像一些系统服务调用应用进程的时候会使用oneway,比如AMS调用应用进程启动Activity,这样就算应用进程中做了耗时的任务,也不会阻塞系统服务的运行。
  • 串行化处理:指对于一个服务的AIDL接口而言,所有的oneway方法不会同时执行,binder驱动会将他们串行化处理,排队一个一个调用。

客户端Client调用Service的函数Func,执行的流程如下:
Binder调用流程图

通过上面的两张图,应该能够清晰的了解到整个Binder的执行过程了

Binder的架构

上面一节我们对远程进程调用代码执行过程有个初步了解,在Android开发中,我们大量使用到了系统Service,比如媒体播放、各种传感器以及WindowManagerService等等。那么Android是怎么管理这些服务,并且让用户跨进程调用这些服务呢?首先我们看看调用系统服务的过程。在Android开机启动过程中,Android会初始化系统的各种Service,并将这些Service向ServiceManager注册(即让ServiceManager管理)。客户端想要得到具体的Service直接向ServiceManager要即可。客户端首先向ServiceManager查询得到具体的Service引用,然后通过这个引用向具体的服务端发送请求,服务端执行完成后就返回。

先看一下Client、Service、ServiceManager三者之间的关系:

Binder架构

当Service创建的时候,首先在ServiceManager中注册一下地址,Client在ServiceManager中查找对应Service的地址,然后根据地址进行请求,Service做出响应。
上图简单介绍了以下三者时间的关系,当然真正的关系不是这么简单的,涉及到Framework层、JNI层、Native层和Kernel层

Binder架构

从上图中可以看到,真正实现跨进程通信是在Kernel层。我们平时说Binder相对于其他的进程间通信方式的优点是,在多进程间传递数据时,只会进行一次数据拷贝,这样的说法是是有歧义的。在Kernel层这样说是对的,但是从Framework到Kernel,Kernel到Framework都会进行内存拷贝。也就是上图的ioctl方法。

Binder驱动实现原理

上述的第三个问题,也就是Binder驱动实现的原理,只要能知道上述答案,那下面就不需要看了。重新回顾一下这个问题:客户端持有远程进程的某个对象引用,然后调用引用类中的函数,远程进程的函数就执行了。学过操作系统的同学都知道,不同的进程之间是不共享资源的。也就是说,客户端持有的这个对象跟远程进程中的实际对象完全是两个不同的对象。客户端调用引用的对象跟远程进程中的对象不是同一个,那问题就来了,为什么调用客户端的这个远程对象的引用,远端进程相应的方法就会被调用?先看下面这幅图:

服务端跨进程的类都要继承Binder类。我们所持有的Binder引用(即服务端的类引用)并不是实际真实的远程Binder对象,我们的引用在Binder驱动里还要做一次映射。也就是说,设备驱动根据我们的引用对象找到对应的远程进程。客户端要调用远程对象函数时,只需把数据写入到Parcel,在调用所持有的Binder引用的transact()函数,transact函数执行过程中会把参数、标识符(标记远程对象及其函数)等数据放入到Client的共享内存,Binder驱动从Client的共享内存中读取数据,根据这些数据找到对应的远程进程的共享内存,把数据拷贝到远程进程的共享内存中,并通知远程进程执行onTransact()函数,这个函数也是属于Binder类。远程进程Binder对象执行完成后,将得到的写入自己的共享内存中,Binder驱动再将远程进程的共享内存数据拷贝到客户端的共享内存,并唤醒客户端线程。整个过程就完美解释了两个进程间为什么能够进行通信,所有的实现都是在Kernel层去实现,屏蔽了细节,我们只需要实现Binder接口就可以轻松的实现跨进程通信了。

Binder机制运用

好了,现在对Binder机制已经理解了,我们再看看Android是怎么运用Binder的。再现前面代码:

//获取WindowManager服务引用
WindowManager wm = (WindowManager)getSystemService(getApplication().WINDOW_SERVICE);  
//布局参数layoutParams相关设置略...
View view=LayoutInflater.from(getApplication()).inflate(R.layout.float_layout, null);  
//添加view
wm.addView(view, layoutParams);

这段代码前面已经出现过。getSystemService(getApplication().WINDOW_SERVICE);函数内部原理就是向ServiceManager查询标识符为getApplication().WINDOW_SERVICE的远程对象的引用。即WindowManager对象的引用,这个引用的真正实现是WindowManager的某个代理。得到这个引用后,在调用addView时,真正的实现是在代理里面,代理把参数打包到Parcel对象中,然后调用transact函数(该函数继承自Binder),再触发Binder驱动的一系列调用过程,在Binder驱动实现原理一节中有具体介绍,忘记了的同学可以返回继续看。关于Binder的代理对象,可以参考AIDL工具生成的代码,这里不再具体介绍。

简单理解 Binder 机制 简单理解 Binder 机制一、为什么要用 Binder二、Binder 进程间通信机制三、Java 层中的 Binder 分析关键一:getIServiceManager()问题一:getIServiceManager() 方法返回是什么,ServiceManager 的代理对象吗关键 1.1:ServiceManagerNative.asInterface() 需要关键 1.2 的返回值作为参... 阅读详情

相关推荐

Binder机制总结

在android中进行跨进程通信通常有以下几种方式: 使用Intent 使用文件共享 使用Messenger 使用AIDL 使用ContentProvider 其中Intent中可以携带Bundle,而Bundle实现了Parcelable接口,所以可以在不同的进程间进行传输。文件共享就是读写文件,比如常用的SharedPreferences就是以XML来存储的文件。而Messenger...

流月的博客 3377

Binder原理深入解析(二)

1. Binder概述 从IPC角度来说:Binder是Android中的一种跨进程通信方式,该通信方式在linux中没有,是Android独有; 从Android Driver层:Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder; 从Android Native层:Binder是创建Service Manager以及BpBinder/BBinder模型,搭建与binder驱动的桥梁; 从Android Framework层:Binder是各种Manager(Acti

Android 1954

别再用MounRiver了!在VSCode里用PlatformIO搞定CH32V208开发(附完整配置流程)

本文详细介绍了如何在VSCode中使用PlatformIO进行CH32V208开发,替代传统的MounRiver Studio。通过完整的配置流程和优化技巧,开发者可以构建高效、现代化的RISC-V开发环境,显著提升编译速度和开发效率。

weixin_28711397的博客 532

【Android面试题】Android Framework核心面试题—— Binder线程池的工作过程是什么样?

Binder主线程:进程创建过程会调用startThreadPool()过程中再进入spawnPooledThread(true),来创建Binder主线程。编号从1开始,也就是意味着binder主线程名为binder_1,并且主线程是不会退出的。Binder普通线程:是由Binder Driver来根据是否有空闲的binder线程来决定是否创建binder线程,回调spawnPooledThread(false) ,isMain=false,该线程名格式为binder_x。

datian1234的博客 594

深入解析Apollo Lattice Planner:自动驾驶轨迹规划的核心算法与实践

本文深入解析了百度Apollo自动驾驶平台中的核心轨迹规划算法——Lattice Planner。文章详细阐述了其作为车辆“即时决策者”的工作原理,通过“采样-评估”的六步流程(Frenet坐标转换、状态采样、轨迹生成、硬约束过滤、代价函数打分及决策平滑),在复杂路况下实时规划出安全、舒适、高效的行驶轨迹。该算法是自动驾驶实现智能决策与精准控制的关键技术。

weixin_29090677的博客 829

告别手动改图!用Python+PyWin32驱动SolidWorks,实现参数自动化修改(保姆级避坑指南)

本文详细介绍了如何利用Python和PyWin32驱动SolidWorks实现参数自动化修改,提供从环境配置到API连接的工业级解决方案。通过实战案例和避坑指南,帮助工程师高效搭建自动化脚本工作流,显著提升设计效率。

weixin_30614109的博客 738

Android Binder机制和线程池

Binder线程池通过高效的线程管理和优化策略,确保了Android系统中多个进程间的通信能够高效、安全地进行。它的工作原理包括请求入队、线程调度和请求处理三个步骤,通过这些步骤,Binder线程池实现了对Binder请求的并发处理,提高了系统的整体性能和用户体验。

望佑 1441

STM32G0/G4电机控制中三角函数与浮点运算优化实战

三角函数(sin/cos)和浮点运算是电机矢量控制(FOC)的核心基础,直接影响Clark/Park变换、SVPWM及观测器的实时性与精度。在资源受限的MCU上,标准math.h库因无硬件FPU支持而引发严重时序抖动,导致电流环延迟、转矩脉动增大甚至系统复位。通过硬件加速(如STM32G4的CORDIC协处理器)或定制化定点算法(如STM32G0的查表+线性插值),可将sin/cos计算从数十微秒压缩至1–3 μs量级,提升30倍以上效率。该方案广泛适用于BLDC/PMSM驱动、伺服控制及高动态响应嵌入式运

weixin_35751412的博客 107

Android Binder 线程池和线程池工作流程

介绍了android binder线程池的常见类和线程池的工作方式

低头赶路,敬事如仪 2461

云原生之容器编排实践-在K8S集群中使用Registry2搭建私有镜像仓库

基于前面搭建的3节点 Kubernetes 集群,今天我们使用 Registry2 搭建私有镜像仓库,这在镜像安全性以及离线环境下运维等方面具有重要意义。作为测试环境,本次使用 Registry2 搭建了私有镜像仓库,实际生产环境建议使用 Harbor;创建了一个 local-storage 的 StorageClass ,并使用本地磁盘的方式创建使用 PV ,实际建议使用 NFS 。

Heartsuit的博客 2460

【AI编程】Qoder AI 编程工具从部署到深度使用实战详解

Qoder AI 编程工具从部署到深度使用实战详解

congge 8333

简单理解Binder机制的原理

一、概述 Android系统中涉及到多进程通信底层都是依赖Binder IPC机制。例如当进程A中的Activity想要向进程B的Service通信,这就需要用到IPC。不仅如此,整个Android系统架构中,大量采用了Binder机制作为IPC(进程间通信)方案。 当然也存在其他的通信方式,如管道、消息队列、socket、内存共享、SystemV等。那为什么Android不使用这些原有的技术,而...

慕涵的博客 5638

廉价却有效?ESD防护中的电容

摘要:在成本敏感型电子产品设计中,多层陶瓷电容(MLCC)可作为TVS二极管的替代方案用于静电放电(ESD)防护。其工作原理是通过电容充放电特性吸收静电能量,而非电压钳位。计算表明100nF/50V MLCC可有效缓冲8kV静电冲击,但存在吸收能量有限、无自恢复等局限。建议将MLCC作为一级缓冲措施,配合TVS等器件形成多级防护,并优先选择X7R材质、100nF容值、50V耐压的0402/0603封装MLCC。该方案在低速信号和电源引脚防护中具有显著成本优势,但不能完全替代专业ESD抑制器。

硬核科技 430

简单明了,彻底地理解Binder

你是不是看过很多Binder文章但是还是对Binder没有一个深刻理解?不是那些文章讲得不够好,主要是存在两种情况,一种是讲的深,全C代码~,对我这种专做Java的人来说没有心情往下看;另一种是只讲framework层,Binder驱动并没有具体提,导致我们会用Binder,也大致能说的出一些原理,可并没有一个完整的深刻认知。那么接下来让我们一起学习Binder吧,相信接下来的内容会让你有一定的收获

huachao1001的专栏 4万+

SQL Server数据库备份与恢复

在 SQL Server 中,数据库备份与恢复是保障数据安全的核心操作。

zjw541806的博客 1876

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Android:安卓学习笔记之Binder 机制的简单理解和使用

Binder 机制 的简单理解和使用Binder 机制参考 Binder 机制 参考 1、图解Android中的Binder机制 2、Android Binder(也许是最容易理解的) 3、图文详解Binder跨进程通信原理 4、Android 接口定义语言 (AIDL) ...

JMW1407的博客 1万+

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Binder机制 简单理解

一、概述 Android系统中,涉及到多进程间的通信底层都是依赖于Binder IPC机制。例如当进程A中的Activity要向进程B中的Service通信,这便需要依赖于Binder IPC。不仅于此,整个Android系统架构中,大量采用了Binder机制作为IPC(进程间通信)方案。 当然也存在部分其他的IPC方式,如管道、SystemV、Socket等。那么Android为什么不使用这...

ZhangJiqun&191cm&85kg 629

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Binder机制深入理解

每一个应用程序都是由一些Activity和Service组成的,这些Activity和Service有可能运行在同一个进程中,也有可能运行在不同的进程中。作为一名Android开发,我们每天都在和Binder打交道,虽然可能有的时候不会注意到,譬如:startActivity的时候,会获取AMS服务,调用AMS服务的startActivity方法startActivity传递的对象为什么需要序列化bindService为什么回调的是一个IBinder对象多进程应用,各个进程之间如何通信。

杨充 3868

简单理解binder机制

简单理解binder机制以及其对比传统socket的优势

weixin_47056106的博客 1017

3分钟带你看懂android的Binder机制

Android是基于Linux内核的,所以Android要实现进程间的通信,其实大可使用linux原有的一些手段,比如管道,共享内存,socket等方式,但是Android还是采用了Binder作为主要机制,说明Binder具有无可比拟的优势。

2401_86968256的博客 2271

android 系统核心机制binder(14)binder调试总结

该系列文章总纲链接:专题分纲目录 android 系统核心机制 binder 1binder调试基础解读 1.1binder的设备节点简单解读 binder调试相关的设备节点再目录/sys/kernel/debug/binder目录下,节点内容如下所示: 这里可以看到binder下所有通信进程信息,打开后cat 其中一个,内容如下所示: 这里包含了该进程中binder相关内容,比如:Binder线程池(thread)、实体对象(binder_node)、引用对象(binder_ref)..

wangdsh的博客 6579

深入理解Binder机制

Binder概述   Binder其前身是由Be Inc.和Palm,Inc.开发的OpenBinder,而后Google将其带入Android系统作为主要的跨进程通信技术使用。Binder之所以能被Google青睐跟其优越的传输性能及安全性能是分不开的。在传输性能上,传统的linux系统IPC如Socket、管道、消息队列等在跨进程传输时数据会被拷贝2次,而Binder则利用mmap只需一次拷贝...

乌啼夜的酒痕 2684

从概念上理解什么是Binder?

前言 Android有很多跨进程通信方式,比如:Bundle(四大组件)、文件共享、AIDL、Messenger、ContentProvider、Socket,除了文件共享和Socket,其他的方式都是基于Binder,那Binder究竟是什么,本文将从概念上解开疑惑。 一、什么是Binder? 对于Binder通常有以下几种解释: 1.Binder机制是Android系统独有的I...

Jeffrey的博客 3328

通过MediaPlayer简单理解Binder的使用

目录 一、说明 二、MediaPlayer中的Binder 1、MediaPlayer的UML图 2、MediaPlayerService的初始化 3、MediaPlayer的初始化 4、MediaPlayer与MediaPlayerService的通信 一、说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和...

qq_15682941的博客 702

【android】binder机制 binder协议

(关于_IOWR,_IOW,_IOR,_IO请参考linux命令码(_IO宏) ) 一.设备文件/dev/binder ioctl命令 #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) //读写命令 #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, int64_t)

paomadi的专栏 2750
上一篇: RxJava学习笔记
下一篇: 类加载器与双亲委派模型
Bobby_lyc
博客等级 码龄16年 1164粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值