简单理解Binder机制的原理

Binder机制原理解析 Binder机制原理解析 前言 我们都知道Android应用程序由Activity、Service、Broadcast Receiver、Content Provider四大组件构成的,他们可能运行在不同进程中,还有Android系统中还有各种服务,例如Actiivty管理服务ActivityManagerService、电源管理服务PowerManagerService、显示管理服务DisplayManagerService、包管理服务PackageManagerService等服务,这些服务在都在系统进 阅读详情

一、概述

Android系统中,涉及到多进程间的通信底层都是依赖于Binder IPC机制。例如当进程A中的Activity要向进程B中的Service通信,这便需要依赖于Binder IPC。不仅于此,整个Android系统架构中,大量采用了Binder机制作为IPC(进程间通信)方案。

当然也存在部分其他的IPC方式,如管道、SystemV、Socket等。那么Android为什么不使用这些原有的技术,而是要使开发一种新的叫Binder的进程间通信机制呢?

为什么要使用Binder?

性能方面

在移动设备上(性能受限制的设备,比如要省电),广泛地使用跨进程通信对通信机制的性能有严格的要求,Binder相对出传统的Socket方式,更加高效。Binder数据拷贝只需要一次,而管道、消息队列、Socket都需要2次,共享内存方式一次内存拷贝都不需要,但实现方式又比较复杂。

安全方面

传统的进程通信方式对于通信双方的身份并没有做出严格的验证,比如Socket通信ip地址是客户端手动填入,很容易进行伪造,而Binder机制从协议本身就支持对通信双方做身份校检,因而大大提升了安全性。

二、 Binder

IPC原理

从进程角度来看IPC机制

每个Android的进程,只能运行在自己进程所拥有的虚拟地址空间。对应一个4GB的虚拟地址空间,其中3GB是用户空间,1GB是内核空间,当然内核空间的大小是可以通过参数配置调整的。对于用户空间,不同进程之间彼此是不能共享的,而内核空间却是可共享的。Client进程向Server进程通信,恰恰是利用进程间可共享的内核内存空间来完成底层通信工作的,Client端与Server端进程往往采用ioctl等方法跟内核空间的驱动进行交互。

Binder原理

Binder通信采用C/S架构,从组件视角来说,包含Client、Server、ServiceManager以及binder驱动,其中ServiceManager用于管理系统中的各种服务。架构图如下所示:

Binder通信的四个角色
Client进程:使用服务的进程。

Server进程:提供服务的进程。

ServiceManager进程:ServiceManager的作用是将字符形式的Binder名字转化成Client中对该Binder的引用,使得Client能够通过Binder名字获得对Server中Binder实体的引用。

Binder驱动:驱动负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。

Binder运行机制

图中Client/Server/ServiceManage之间的相互通信都是基于Binder机制。既然基于Binder机制通信,那么同样也是C/S架构,则图中的3大步骤都有相应的Client端与Server端。

注册服务(addService):Server进程要先注册Service到ServiceManager。该过程:Server是客户端,ServiceManager是服务端。

获取服务(getService):Client进程使用某个Service前,须先向ServiceManager中获取相应的Service。该过程:Client是客户端,ServiceManager是服务端。

使用服务:Client根据得到的Service信息建立与Service所在的Server进程通信的通路,然后就可以直接与Service交互。该过程:client是客户端,server是服务端。

图中的Client,Server,Service Manager之间交互都是虚线表示,是由于它们彼此之间不是直接交互的,而是都通过与Binder驱动进行交互的,从而实现IPC通信方式。其中Binder驱动位于内核空间,Client,Server,Service Manager位于用户空间。Binder驱动和Service Manager可以看做是Android平台的基础架构,而Client和Server是Android的应用层,开发人员只需自定义实现client、Server端,借助Android的基本平台架构便可以直接进行IPC通信。

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);

注册服务(addService):在Android开机启动过程中,Android会初始化系统的各种Service,并将这些Service向ServiceManager注册(即让ServiceManager管理)。这一步是系统自动完成的。

获取服务(getService):客户端想要得到具体的Service直接向ServiceManager要即可。客户端首先向ServiceManager查询得到具体的Service引用,通常是Service引用的代理对象,对数据进行一些处理操作。即第2行代码中,得到的wm是WindowManager对象的引用。

使用服务:通过这个引用向具体的服务端发送请求,服务端执行完成后就返回。即第6行调用WindowManager的addView函数,将触发远程调用,调用的是运行在systemServer进程中的WindowManager的addView函数。

使用服务的具体执行过程

  • client通过获得一个server的代理接口,对server进行调用。
  • 代理接口中定义的方法与server中定义的方法时一一对应的。
  • client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成Parcel对象。
  • 代理接口将Parcel发送给内核中的binder driver。
  • server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回。
  • 整个的调用过程是一个同步过程,在server处理的时候,client会block住。因此client调用过程不应在主线程。

以上就是Binder机制原理的简单介绍,后面会以AIDL来具体介绍Binder机制的使用,加深对其的了解。

为了保护进程空间不被别的进程破坏或者干扰,Linux的进程是相互独立的(进程隔离),而且一个进程空间还分为用户空间和内核(Kernel)空间,相当于把Kernel和上层的应用程序抽像的隔离开。这里有两个隔离,一个进程间是相互隔离的,二是进程内有用户和内核的隔离。

Binder框架定义了四个角色:Server,Client,ServiceManager以及Binder驱动。其中Server,Client,ServiceManager运行于用户空间,驱动运行于内核空间。这四个角色的关系类似:Server是服务器,Client是客户终端,ServiceManager是服务注册中心(类似房屋中介)。

要进行Client-Server之间的通信,从面向对象的角度,在Server内部有一个Binder实体,在Client内部有一个Binder对象的引用,其实就是Binder的一个代理,Client通过对Binder引用间接的操作Server内部的Binder实体,这样就实现了通信。

但是现在的问题是会有很多个提供不同服务的Server(比如有媒体播放服务,音视频捕获服务等),而且会有很多Client(比如多个应用都要调用媒体播放服务),那么我们怎么才能够实现正确的Client调用正确的Server呢?就好比房客怎么才能够租到自己想要租的房子(联系上房东),这个时候中介就起到重要作用,房东想要出租自己的房子就必须要到中介注册,房客想要租房子就要去中介那里找,同样的道理,这里Client就是房客,Server就是房东,ServiceManager就是房屋中介,每个Server如果要提供服务就必须要去ServiceManager那里去注册,ServiceManager在一张查找表中记录一个Server的名字,对应着Server的引用。Client想要获得Server,必须通过名字到ServiceManager取找Server的引用,获得这个Server的binder引用,通过这个binder引用去和Server通信。


Binder机制

首先Binder是Android系统进程间通信(IPC)方式之一。

Binder使用Client-Server通信方式。Binder框架定义了四个角色:Server,Client,ServiceManager以及Binder驱动。其中Server,Client,ServiceManager运行于用户空间,驱动运行于内核空间。Binder驱动程序提供设备文件/dev/binder与用户空间交互,Client、Server和Service Manager通过open和ioctl文件操作函数与Binder驱动程序进行通信。

Server创建了Binder实体,为其取一个字符形式,可读易记的名字,将这个Binder连同名字以数据包的形式通过Binder驱动发送给ServiceManager,通知ServiceManager注册一个名字为XX的Binder,它位于Server中。驱动为这个穿过进程边界的Binder创建位于内核中的实体结点以及ServiceManager对实体的引用,将名字以及新建的引用打包给ServiceManager。ServiceManager收数据包后,从中取出名字和引用填入一张查找表中。但是一个Server若向ServiceManager注册自己Binder就必须通过0这个引用和ServiceManager的Binder通信。Server向ServiceManager注册了Binder实体及其名字后,Client就可以通过名字获得该Binder的引用了。Clent也利用保留的0号引用向ServiceManager请求访问某个Binder:我申请名字叫XX的Binder的引用。ServiceManager收到这个连接请求,从请求数据包里获得Binder的名字,在查找表里找到该名字对应的条目,从条目中取出Binder引用,将该引用作为回复发送给发起请求的Client。

当然,不是所有的Binder都需要注册给ServiceManager广而告之的。Server端可以通过已经建立的Binder连接将创建的Binder实体传给Client,当然这条已经建立的Binder连接必须是通过实名Binder实现。由于这个Binder没有向ServiceManager注册名字,所以是匿名Binder。Client将会收到这个匿名Binder的引用,通过这个引用向位于Server中的实体发送请求。匿名Binder为通信双方建立一条私密通道,只要Server没有把匿名Binder发给别的进程,别的进程就无法通过穷举或猜测等任何方式获得该Binder的引用,向该Binder发送请求。


###为什么Binder只进行了一次数据拷贝?

Linux内核实际上没有从一个用户空间到另一个用户空间直接拷贝的函数,需要先用copy_from_user()拷贝到内核空间,再用copy_to_user()拷贝到另一个用户空间。为了实现用户空间到用户空间的拷贝,mmap()分配的内存除了映射进了接收方进程里,还映射进了内核空间。所以调用copy_from_user()将数据拷贝进内核空间也相当于拷贝进了接收方的用户空间,这就是Binder只需一次拷贝的‘秘密’。

最底层的是Android的ashmen(Anonymous shared memory)机制,它负责辅助实现内存的分配,以及跨进程所需要的内存共享。AIDL(android interface definition language)对Binder的使用进行了封装,可以让开发者方便的进行方法的远程调用,后面会详细介绍。Intent是最高一层的抽象,方便开发者进行常用的跨进程调用。

从英文字面上意思看,Binder具有粘结剂的意思那么它是把什么东西粘接在一起呢?在Android系统的Binder机制中,由一系统组件组成,分别是Client、Server、Service Manager和Binder驱动,其中Client、Server、Service Manager运行在用户空间,Binder驱动程序运行内核空间。Binder就是一种把这四个组件粘合在一起的粘连剂了,其中,核心组件便是Binder驱动程序了,ServiceManager提供了辅助管理的功能,Client和Server正是Binder驱动和ServiceManager提供的基础设施上,进行Client-Server之间的通信。

  • Client、Server和ServiceManager实现在用户空间中,Binder驱动实现在内核空间中
  • Binder驱动程序和ServiceManager在Android平台中已经实现,开发者只需要在用户空间实现自己的Client和Server
  • Binder驱动程序提供设备文件/dev/binder与用户空间交互,Client、Server和ServiceManager通过open和ioctl文件操作函数与Binder驱动程序进行通信
  • Client和Server之间的进程间通信通过Binder驱动程序间接实现
  • ServiceManager是一个守护进程,用来管理Server,并向Client提供查询Server接口的能力

服务器端:一个Binder服务器就是一个Binder类的对象。当创建一个Binder对象后,内部就会开启一个线程,这个线程用户接收binder驱动发送的消息,收到消息后,会执行相关的服务代码。

Binder驱动:当服务端成功创建一个Binder对象后,Binder驱动也会相应创建一个mRemote对象,该对象的类型也是Binder类,客户就可以借助这个mRemote对象来访问远程服务。

客户端:客户端要想访问Binder的远程服务,就必须获取远程服务的Binder对象在binder驱动层对应的binder驱动层对应的mRemote引用。当获取到mRemote对象的引用后,就可以调用相应Binde对象的服务了。

在这里我们可以看到,客户是通过Binder驱动来调用服务端的相关服务。首先,在服务端创建一个Binder对象,接着客户端通过获取Binder驱动中Binder对象的引用来调用服务端的服务。在Binder机制中正是借着Binder驱动将不同进程间的组件bind(粘连)在一起,实现通信。

mmap将一个文件或者其他对象映射进内存。文件被映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会凋零。munmap执行相反的操作,删除特定地址区域的对象映射。

当使用mmap映射文件到进程后,就可以直接操作这段虚拟地址进行文件的读写等操作,不必再调用read,write等系统调用。但需注意,直接对该段内存写时不会写入超过当前文件大小的内容。

使用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次内存数据:一次从输入文件到共享内存区,另一次从共享内存到输出文件。实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域,而是保持共享区域,直到通信完成为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除内存映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。

aidl主要就帮助了我们完成了包装数据和解包的过程,并调用了transact过程,而用来传递的数据包我们就称为parcel

AIDL:xxx.aidl -> xxx.java ,注册service

用aidl定义需要被调用方法接口
实现这些方法
调用这些方法

原文链接:

https://www.jianshu.com/p/4920c7781afe?from=jiantop.com

https://github.com/francistao/LearningNotes/blob/master/Part1/Android/Binder%E6%9C%BA%E5%88%B6.md

Linux·Binder机制原理 Binder机制 原理 阅读详情

相关推荐

Android之Binder原理剖析

binder

zhuhai0613的博客 2808

Binder机制深入理解

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

杨充 3868

Android进阶:六、在子线程中直接使用-Toast-及其原理,安卓binder机制详解

mTN = new TN(context.getPackageName(), looper); } 可以看出这个Looper其实是TN在用,我们看看它的构造函数: TN(String packageName, @Nullable Looper looper) { if (looper == null) { // Use Looper.myLooper() if looper is not specified. looper = Looper.myLooper(); if (looper == null) {

m0_66684810的博客 2927

binder机制详解

很全:亲,耐心看完会有收获的 1.Binder通信机制介绍 这篇文章会先对比Binder机制与Linux的通信机制的差别,了解为什么Android会另起炉灶,采用Binder。接着,会根据Binder的机制,去理解什么是Service Manager,在C/S模型中扮演什么角色。最后,会从一次完整的通信活动中,去理解Binder通信的过程。 1.1 Android与Linux

西红柿炒土豆 5398

Android进程间通信机制Binder简介及学习计划

客户端通过bindService方法绑定到服务端,并通过ServiceConnection回调获取到Binder对象的引用,然后就可以调用Binder对象的方法来实现进程间通信。通过学习Binder的基本概念、工作原理和使用方法,并进行实践,你可以更深入地了解Android进程间通信机制,并能够在实际开发中灵活运用Binder来实现不同组件和应用程序之间的交互。Binder驱动(Binder Driver):位于内核空间的组件,负责处理进程间通信的底层细节。了解Binder的核心组件和它们之间的关系。

JieLun_C的博客 247

国产PHY芯片YT8512H替代LAN8742A的实战指南(STM32F407平台)

本文详细介绍了在STM32F407平台上,使用国产PHY芯片YT8512H替代LAN8742A的完整实战过程。文章深入剖析了硬件设计中的关键信号连接差异(如CRS_DV与RXDV复用)、时钟布线要点,并提供了软件驱动修改、PHY配置及调试排错的系统指南,旨在帮助工程师高效完成国产化替代,规避常见陷阱。

defi6farmer的博客 857

简单理解Binder机制的原理和从AIDL层解析使用方法

推荐参考资料: 如果不想看我下面的一堆文字,建议顺序依次看一下下面的3篇文章,很有收获 https://www.jianshu.com/p/4920c7781afe?from=jiantop.com http://www.cnblogs.com/zc9527/p/5638688.html https://www.cnblogs.com/itgungnir/p/6640120.html 以下内容做记...

威威的专栏 834

Allegro如何进行四层板板层设计

板层的设计

weixin_42499230的博客 3189

android ipc简单理解,Android特有Binder与IPC机制原理初探,看完应该理解一些些。

前言概述Binder网上有很多文章要么讲的深入全是LInux内核指令C语言分析,要么空洞无脑。这里个人理解整理如下。什么是Binder:1.Binder是一个类实现了IBinder接口,目的就是为了IPC服务而存在的。进程间通信的必须依赖的东西。2.Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager…….)和相应的系统底层M...

weixin_32722209的博客 319

可信启动方案设计

本博客简要解释了TF-A中的Measured-Boot可信启动设计实现。

AI-安全-功耗 1204

【数据集】未来不同情景下预测数据:如人口、土地利用等

未来不同情景下预测数据:如人口、土地利用等

WW、forever的博客 2994

binder通信

参考:简单理解Binder机制的原理

xuyin1204的博客 113

手把手教你学基带SOC芯片(4.2)--基带soc芯片的存储器设计

基带 SoC 中的存储器设计需要综合考虑功耗、成本和性能等因素。SRAM 适合高速缓存,DRAM 适合主内存,Flash 存储器适合非易失性存储。通过优化存储单元设计、阵列布局和外围电路,可以提高存储器的性能和效率。

MHD0815的博客 350

Android Binder原理解析

系统就会为我们把对应的远程服务端唤醒,看源码知道是通过ServiceManager 去远程服务用ClassLoader反射的方式启动需要启动的service。这里把我们传过来的对象进行解析,并回调了Stub的抽象方法addBook,这个抽象方法就是我们再Service中重写的那个方法。//将一个IBinder对象转换成一个com.love.candy.aidl,这里就是我们平常用到的那个方法了。//这里会通过Binder的onTransact方法回调到我们Stub中。//这里的值和Proxy中的值对应。

2501_90471794的博客 1372

Python 实战:全面解析“微信搜一搜”内容爬取,从入门到企业级架构

本文将带你从零搭建爬虫项目,采用 Requests、Scrapy、Selenium、Proxy 池、中间人监控(如 Fiddler/mitmproxy)、分布式调度、数据库持久化、断点续抓等方案,实现可持续、抗封能力强的内容抓取系统。理解“微信搜一搜”页面结构与 Javascript 渲染逻辑;使用 Scrapy 框架搭建分布式爬虫;使用 Selenium 模拟浏览器抓取;构建代理池提升爬取成功率;对抗验证码、IP 封禁与 cookie 过期问题;

2201_76125261的博客 1393

HBase骚操作之数据加载方式BulkLoad

本文研究了一种HBase BulkLoad的入库方式,该方式利用HBase的数据信息按照特定格式存储在hdfs内这一原理,直接在HDFS中生成持久化的HFile数据格式文件,然后上传至合适位置,即完成巨量数据快速入库的办法。该方式配合MapReduce完成,高效便捷,而且不占用Region资源,增添负载,在大数据量写入时能极大的提高写入效率,并降低对Hbase节点的写入压力。HBase BulkLoad对于异构数据源的合并及大量数据一次性导入具有重要指导意义,相比HBase Put操作在性能上具有较高的优势

石榴姐yyds 7789

Android Binder机制和用例

Android 系统是基于 Linux 内核的,Linux 已经提供了管道、消息队列、共享内存和 Socket 等 IPC 机制。那为什么 Android 还要提供 Binder 来实现 IPC 呢?主要是基于性能、稳定性和安全性几方面的原因。这里我们先从 Linux 中进程间通信涉及的一些基本概念开始介绍,然后逐步展开,向大家说明传统的进程间通信的原理。进程隔离进程空间划分:用户空间(User Space)/内核空间(Kernel Space)系统调用:用户态/内核态。

martin_liang的专栏 700

IPGUARD客户端与应用程序冲突

客户端与应用程序冲突 症状 安装客户端之后,客户端的某些程序无法运行或使用过程中出现异常,卸载客户端后恢复正常。 原因分析 可能是客户端的某些功能与应用程序发生冲突导致。 解决方法 当出现这样的情况时,可以按照以下步骤确认。 步骤1:屏蔽主动注入 在客户端配置策略中,增加配置策略hookapi_disinj,值为1;待策略同步到客户端后,重启客户端确认问题是否解决。如果解决,则转到...

IP-Guard专栏 1410

Android中的Binder机制的简要理解二

接着上篇binder简要介绍(见 http://www.linuxidc.com/Linux/2012-07/66195.htm ),我们来分析binder机制的设计。binder主要框架分为三个部分:服务端,binder驱动,客户端。 binder在Android最常见的使用场景就是一个程序的activity与系统service进行交互。比如我通过wifi的service来获取wifi控制

sunxingzhesunjinbiao的专栏 3512

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Android系统中的广播(Broadcast)机制简要介绍和学习计划

在Android系统中,广播(Broadcast)是在组件之间传播数据(Intent)的一种机制;这些组件甚至是可以位于不同的进程中,这样它就像Binder机制一样,起到进程间通信的作用;本文通过一个简单的例子来学习Android系统的广播机制,为后续分析广播机制的源代码作准备。        在Android系统中,为什么需要广播机制呢?广播机制,本质上它就是一种组件间的通信方式,如果是两个组件

老罗的Android之旅 9万+

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

上一篇: JVM
下一篇: SurfaceView
augfun
博客等级 码龄10年 311粉丝 662原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值