Android Binder 初步探究(基本原理)

前言

本文可以视为 Binder 学习指南为什么Android 要采用 BInder 作为 IPC 机制 两篇文章的学习笔记,因此文章仅为笔者个人复习使用 ,同时希望能给 对以上两篇文章有所了解的朋友 提供参考。

一、概述

1.Binder的含义

binder 是 Android 系统实现IPC(跨进程通信)的机制,它沟通和联系了各个组件,是Android系统最为重要的成员之一。

2.进程隔离

进程:
进程是操作系统中的一个重要概念,基本的 CS 课程都会讲到,不同进程之间的数据是不共享的(内存隔离),那么进程之间要进行数据传递,就需要有一套对应的系统机制了。

进程隔离:
进程隔离使用了虚拟地址空间(这个概念就不引申了),A 进程和B进程的虚拟地址不同,以此避免 A进程的数据写入B进程。

3.用户空间 与 内核空间:

内核:
Linux Kernel ,它是系统运行的核心,独立于普通的应用程序。它可以访问受到保护的内存空间,同时也有权限访问所有硬件资源。

用户:
这里的用户就是上层的普通应用程序的意思

为什么区分用户空间 与 内核空间?
从内核的设定可以看出,它是非常重要的,也拥有极高的权限,因此不可以让上层应用程序随意的调用和访问它,所以需要一套保护机制,告诉应用程序,你只可以访问哪些特定的资源。所以就从逻辑上抽象出用户空间和内核空间,将它们隔离开来。

4.用户态 与 内核态

系统调用
虽然说抽象出了 用户空间 和 内核空间将它们隔离开,但是不可避免的,应用程序会有需要访问内核的时候,例如访问文件、使用网络。这时候,就有了系统调用的概念。
系统调用是用户空间访问内核空间的唯一入口接口,通过这种方式,所有资源的访问都会在内核的控制之下了,安全性自然大大增加。

用户态:
当在执行上层应用程序自己的代码的时候,就称之处于用户态,这时候进程的特权等级最低(3级)

内核态:
当通过系统调用,执行内核代码的时候,就称之处于内核态,这时候进程的特权等级最高(0级)。只有在满足一定特权等级的时候,CPU才能执行对应的特权指令。

5.内核模块 与 binder驱动:

用户空间与用户空间通信
用户空间与用户空间之间想要通信,第一时间想到的当然是让内核提供支持,毕竟不同的用户空间都可以访问同一个内核空间。
linux内核中的socket和管道都是解决用户空间之间通信问题的,但是Binder并不是Linux内核的一部分啊,这时候就用到了Linux的动态可加载内核模块机制(LKM)

内核模块
在Linux中,模块不能单独运行,但是它可以单独编译,内核模块就是在运行时再 连入 链接到内核中,作为内核的一部分 ,在内核空间中运行。
在Android系统里,为了解决用户进程之间通信问题而引入的内核模块就是:binder驱动。

binder 驱动:
驱动就是操作硬件的接口,为了实现binder通信的过程,binder使用了一种“硬件”,因此这个模块被叫做binder驱动。

二、为什么是 Binder

1.简单描述

性能更好:
在移动设备上(尤其是早期的Android设备,硬件水平太差了),性能毫无疑问是非常重要的一项指标,binder机制比起传统的socket和管道等有更好的性能:Binder数据拷贝只需要一次(匿名共享内存),而管道、消息队列、Socket都需要2次。

安全性更高:
传统的跨进程通信机制,通常都没有针对通信的两端做身份上的校验(例如socket的IP地址完全可以伪造),而Android系统作为一个开放的生态,必然对安全性有更高的要求。
binder机制从协议上就 ~~设置了 ~~ 支持了对通信双方的身份校验,提高了安全性。这也是Android权限模型的基础

2.详细解释(暂且留空,等仔细看完gityuan大佬那个回答再来补充)

三、Binder 通信模型

1.通信过程中的角色

通信的双方:
Binder通信的双方一般称为:Server端 和 Client端,可以类比于网络通信中的服务端和客户端,实际上它们往往就是两个用户进程

通信录:
就像打电话时候需要的电话簿一样,通信录记录了 Server 端的地址信息,这样 Client 端才能找到对应的 Server 端,并向它发送消息。

通信录如何知道 Server 端的信息呢?
这就要求Server端自己要去通信录里面注册了,Binder通信的通信录工作,是由 ServiceManager 来完成的,也可以简称为 SM(不要想歪了,这是失眠的意思

基站:
同样以打电话来类比,一次通信的过程,当然少不了基站的支持,只有依靠它才能真正实现在通信双方之间传递消息
Binder通信的基站工作,是由Binder驱动来完成的

来人,给公子上图
image.png

2.一次基本的通信过程
  1. 首先是建立通信录(SM):一个进程申请成为ServiceManager,Binder驱动同意之后,SM进程就开始工作了,管理 Service 。原文中特意说明这里是Service,不是Server,我个人理解意思是说一次通信的 Client 进程,可能再跟另一个进程通信时,它又是 Sever 了,也就是一个进程会扮演 Client 和 Server 两个角色。
  2. 在通信录中注册(Server -> SM):如前文所说,SM也没办法凭空知道所有Server的信息,所以需要各个Server 自己在 SM 中注册,告知 SM 自己的名字和对应的地址信息
  3. 开始通信(Client -> SM -> Server):终于到了发送消息的这一步了,Client 想跟某个 Server 通信,就会先去 SM 中查询对应 Server 的信息,然后通过 binder 驱动,与对应的 Server 联系上,开始打电话了(通信是一来一回的,这里用发消息来类比就不合适了)。

四、Binder 机制跨进程原理

1.有关于通信

常规的进程间通信方式:
对于两个进程 A 和 B 来说,内核可以访问它们两个的数据,最常见的跨进程通信方式,当然就是利用内核。
例如 A 要向 B 发送一段数据,那么 A 就可以将数据拷贝到内核空间,然后内核再将数据拷贝到 B。
前面说到,用户空间操控内核空间需要通过系统调用,刚好Linux也提供了对应的系统调用:copy_from_user, copy_to_user。

Binder 机制跨进程通信的定义:
通信这个概念其实是比较宽泛的
Binder 机制实现跨进程通信,其实是指 Client 进程可以访问 Server 进程中的对象及其方法,这当然也是通信的一种方式
Binder 并没有用上述的常规的进程间通信方式

2.Binder 机制

隐藏步骤:一个进程申请成为ServiceManager,也就是SM进程

  1. Server 端向 SM 注册:Server 端要向 SM 注册,告知 SM 自己的信息和自己有什么能力(提供什么方法)。例如:进程名是 Zhangsan ,拥有一个 Object 对象,它有个 add 方法。

  2. Client 端从 SM 查询:Client 端想要访问 Zhangsan的这个 Object 对象,就需要联系 SM 查询,让SM给它返回对应的对象,但是注意,这里返回的对象不是原对象。

  3. Binder 驱动对查询的中间处理:
    数据在内核空间传递的时候,会经过 Binder 驱动,Binder 驱动判断到这是一个跨进程的调用,它不会将真正的 Object 对象返回给 A ,而是会返回一个 ObjectProxy 对象。
    这个对象的方法和 Object 对象一模一样,它也有 add 方法,但是它不具备真正 Object 对象所拥有的能力,也就是它是一个代理对象,是假的。

  4. Client 端调用:Client 拿到 ObjectProxy 对象之后,并不会感知到它和 Object 对象不一样,它还是照常当作在调用 Object 的 add 方法。

  5. Binder 驱动对调用的中间处理:
    这个调用当然又要经过 Binder 驱动,Binder 驱动 通过查表判断到 这是 ObjectProxy 对象的调用,就会去调用真正的 Object 对象的 add 方法,并且将得到的结果,通过 ObjectProxy.add 方法返回给进程 A。由此就完成了一次跨进程的调用,而 A 进程的调用方在此过程中其实是完全无感知的。

  6. 隐藏的内容 – Server 与 SM 的通信:
    上述过程其实省略了很多细节,例如 Server 进程与 SM 大多数时候肯定也不是同一个进程的,那么 Server 进程向 SM 注册的过程,本身也是一次跨进程通信,自然也是利用了 Binder 机制
    SM 中持有的 Object 对象,自然也不是真正的 Object 对象,其实它也是一个 代理对象,是一个 ObjectProxy 。
    Server 进程的本地对象仅有一个,只有这个是有真正的能力的,其他进程所拥有的全部都是它的代理

  7. 总结:Client 进程持有的只是 Server 端的代理,代理对象协助Binder驱动完成了跨进程通信。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Binder是在Android系统中用于进程间通信(IPC)的一种机制Binder提供了一种高效的、低延迟的IPC方式,使得不同进程之间可以安全、可靠地进行通信。 下面是Android Binder的详细原理: 1. Binder驱动 Android Binder的底层是由Binder驱动实现的,它是一个在内核空间运行的模块,用于处理进程间通信。Binder驱动提供了一些API给用户空间的Binder库使用,这些API包括创建Binder对象、发送消息、接收消息等。 2. Binder对象 在Android系统中,每个进程都有一个唯一的Binder对象。Binder对象是由Binder驱动动态创建的,它包含了一个通信线程(Binder线程),用于处理当前进程与其他进程之间的通信。当进程需要与另一个进程通信时,它会向Binder驱动发送请求,请求创建一个新的Binder对象。 3. Binder代理和存根 当进程A需要与进程B通信时,它会向Binder驱动发送请求,请求创建一个新的Binder对象。Binder驱动会在进程B中创建一个Binder代理对象和一个Binder存根对象。 Binder代理对象是在进程A中创建的,它是一个轻量级的对象,用于向进程B发送请求。当进程A需要向进程B发送请求时,它会通过Binder代理对象向Binder驱动发送请求,请求将消息发送给进程B。 Binder存根对象是在进程B中创建的,它是一个重量级的对象,用于接收进程A发送的请求,并将请求转发给进程B中的相应组件。当进程B接收到来自进程A的请求时,它会通过Binder存根对象处理请求,并将结果返回给Binder驱动,最终返回给进程A。 4. 远程代理 Android Binder还提供了一种远程代理机制,它可以将一个对象在不同的进程之间传递。当进程A需要访问进程B中的某个对象时,它会先向Binder驱动发送请求,请求获取该对象的远程代理。Binder驱动会在进程A中创建一个轻量级的远程代理对象,用于向进程B发送请求,并将请求转发给进程B中的相应组件。当进程B接收到来自进程A的请求时,它会通过Binder存根对象处理请求,并将结果返回给Binder驱动,最终返回给进程A中的远程代理对象。 以上就是Android Binder的详细原理Android Binder是一个非常重要的组件,它为Android系统中的进程间通信提供了高效、可靠的解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值