Binder机制详解(一)

系列目录

Binder机制详解(二)

Binder机制详解(三)


前言

Binder通信机制是android中不同于Linux的通信机制,那么为什么会有Binder通信机制,为什么不能用linux中已有的进程框架呢?Google工程师究竟是如何考量的?这一切需要从一场恋爱说起


一、爱情例子

1.普通Linux间进程通信方式

故事:男孩和女孩在某次旅游一见钟情,而旅行结束的他们不得不返回各自的工作城市,那个时代还没有微信,由于相隔在不同的城市。相思念的他们只能通过邮局抒发彼此爱慕之情

如果男孩想要给女孩发送信封,需要向本地邮局 寄信。再有全国邮局转发到 女孩所在的本地邮局

最后由女孩所在的本地邮局送到女孩手中

故事中在进程中的角色:

男孩** 称为进程A,工作城市A城,女孩称为进程B,工作城市B城

本地邮局称为用户空间, 全国邮局称为内核空间

本地邮局是他们彼此 离的最近的地方。他们能够在本地邮局直接接受和发送信封

这是普通linux进程通信的方式,那么问题来了:

男孩写好信之后,发送信件给本地邮局 , 相当于一次拷贝 我们把这个过程称为(copy_from_user)

女孩收到当地邮局通知,需要从本地邮局取信。相当于第二次拷贝,我们把这个过程称为(copy_to_user)

两次拷贝究竟性能怎么样,当然拷贝是非常耗性能的,而两次拷贝可以再优化优化。

那binder是怎么做到一次拷贝的呢

2.接着讲爱情的例子(Binder的实现机制)

后来在疫情结束后,这个女孩去了全国邮局依赖的快递公司上班去了,所有的邮件需要用快递公司来处理,刚好这家快递公司处理的是他们两个城市的信件。

这就给女孩创造了便利,不用去本地邮件取信件

但是男孩还是要发送信件。 binder拷贝也是发生在男孩这个地方copy_from_user,女孩由于在快递公司上班,可以随意浏览男孩的信件。不需要再取信件了。也就减少了从本地邮局取快递这次拷贝过程

思考: 大家还记不记的 接收端怎么写的,对! 接收端一定必须是服务Service,接收端不能是其他java对象。Service就是那个女孩。她必须在快递公司上班才能减少一次拷贝。所以这个Service,在通信前会注册在ServiceManager中。而男孩可以是任意对象,出现在任意地方

Linux 已有的进程通信,发送端和接收端可以是任意对象。出现在任意类中。但是必须牺牲多拷贝一次

Android的Binder通信,接受端不能是任意对象,只能是Service,这也节约了一次拷贝,牺牲了开发者的体验

3.Binder少拷贝一次的原理:

全国邮局 相当于内核空间的内存,所有的应用都与内核空间的内存发生频繁的调用,在Binder中传递数据本质上是通过文件读取来实现的

大家记不记得Linux系统 是文件操作系统,都是基于文件展开的。进程通信中 File也能实现进程通信

Binder机制中 在内存与文件中设计了一层映射关系。内核空间的内存是虚的的文件IO是实的。 映射指的是内存与文件的映射,映射是通过mmap函数,

​ 而mmap函数 需要依赖一个文件,这个文件叫做“binder”。 对! 他没有后缀名,他就是一个文件。但是人们习惯性的把它称为binder驱动

我们再来看看实际的是如何映射的

  • 全国邮局中的A城与B城的信件,相当于内核空间内存一部分虚拟内存区域。
  • A城与B城的快递公司,相当于文件实体。实际上邮件是由快递公司转发。邮局与快递公司的合作关系,可以理解内存与文件形成了映射关系(mmap)

4.服务端Service 也通过mmap函数监听文件的变化

一旦有信件到达女孩的公司直接读取出来,而不用去本地邮件取信件。

女孩怎么在公司取出来呢? 大家忘记了女孩在快递公司上班呢,快递公司会给员工分布工作内容

女孩的工作内容是查看快递接收站和快递发送站

这样你说能不能看到男朋友发过来的信件,还不用亲自跑到本地邮局,那不是爽歪歪

绿色部分 是女孩进程,绿色内有两个角色(女孩接触到的 接收站和收发站)

这一套机制的实现基于 aidl文件编译机制

在编译时生成了一个继承自Binder中的IInterface接口(女孩)。接口中有这样一个内部类叫Stub(女孩工作接触的接收站)和一个内部类叫Proxy(女孩工作接触的发送站)

男孩有邮件到了,女孩直接在 快递接收站查看男孩发过来的邮件(Stub中的 onTransact方法)

女孩思恋男孩,跟男孩发送邮件(Proxy中的transact方法)

Stub与Proxy中所有的方法是native直接调用过来的。参数是直接从内核空间传递过来的,不需要发生拷贝。

如果女孩需要给男孩发送消息,也不用跑到本地邮局,直接在 快递发送站,插入一个邮件就好了(调用Proxy的transct方法)

减少一次拷贝发生在 服务端service。直接有nativie层 的Binder调起。不需要再次拷贝

大家看完了 是不是对整个Binder机制有深刻的认识呢

从Binder的底层原理分析,让Android开发者真正了解到Binder的通信机制。从Linux进程通信技术认知到为什么Android会选择Binder作为通信方式,到Linux的进程原理,最后借鉴Binder中mmap函数打造优异的存储框架。

二、用户空间和内核空间

现代计算机都有两种以上的运行模式(普通模式、特权模式),

linux系统只有两层:

用户空间

  • 高优先级模式(特权模式)
  • 低优先级模式(普通模式)

linux系统在高优先级模式中运行系统内核代码以及与硬件密切相关的代码。低优先级运行应用程序与硬件无关部分。

​ 应用程序不能直接操控硬件或者调用内核函数,需借助一系列接口函数申请让系统调用相关代码在内核空间运行,获取代码运行权限。

1.好处

  • ​ 应用程序崩溃不会造成内核崩溃,拿windows举例来说,QQ崩溃掉不会造成程序死机

  • ​ 每个应用程序或者进程都会有自己特定的地址、私有数据空间,程序之间一般不会相互影响

    ​ 例如QQ崩溃不会造成微信的崩溃。空间的隔离极大地提高了系统运行的稳定性。

2.计算机蓝屏带来的启示

计算机蓝屏主要是因为计算机硬件驱动不兼容问题造成,硬件驱动代码运行在内核空间,与kernel运行在相同空间内,所以驱动程序发生问题容易造成系统的崩溃。将用户空间与内核空间隔离开,可减少系统崩溃的可能,提高系统的稳定性。毕竟现实情况中,应用程序崩溃的情况比蓝屏出现的概率要多的多得多。在linux中这种情况可以类比。

​ window有上百个驱动,如蓝牙驱动,主板驱动,声卡驱动,麦克风驱动,显卡驱动,USB驱动等等!驱动过多容易造成蓝屏的出现。他们都运行在内核中。为什么会有这么多驱动。电脑中每一个配件都可以随意组合。形成一个完整的电脑

Android 发现

​ 在Android系统中,虽然也是基于Linux系统,但是这些驱动在Android厂商都已经消失了。全部集成化了、除了Binder驱动外,屏幕驱动,蓝牙驱动外几乎看不到其他驱动,这也是蓝屏比较少的原因

3.在linux中

每一个系统进程都拥有自己私有的地址空间和数据,用户空间造成的进程错误会被局部化,而不会影响到内核或者其他进程。(上面所说QQ和微信的例子)。

当用户进程需要完成在特权模式下才能完成的某些工作时,通过linux向上提供的系统调用接口进入特权模式,然后执行调用所提供的有限功能
​ 应用程序正常情况下都是运行在普通模式下,这部分代码运行的空间称为用户空间,当代码通过系统调用计入到特权级别运行的时候,对应的代码执行空间称为内核空间。

linux系统中每个进程占有4G空间(虚拟空间,并不一定真实占用)

空间分布如下:

  1. 用户空间: 0~(3G-1) 普通的应用程序代码运行在此部分空间中
  2. 内核空间: 3G~(4G-1) 内核代码段,其中驱动就是运行在此部分空间中

4.用户空间与内核空间交流

用户空间应用程序往往需要调用硬件(QQ调用相机拍照)或者运行与系统核心相关的内容(360清理进程),免不了与内核打交道,他们之间调用关系又是怎样呢?

交流关系以open()文件打开函数为例
上层应用在用户空间执行到 open() API函数时,会触发系统软中断,系统调用 系统调用函数 sys_open()系统调用函数,在内核空间执行open代码,这样用户空间的open函数内部代码就取得了在内核空间运行的权限,可以做一些比较牛比较核心的事情。
应用层API函数还有很多,大约有250个左右,涵盖范围包括文件操作、进程控制、网络操作等等。调用原理大致相同。

总结

Binder机制要完全搞懂,我会分几章来讲解,这章通过一个例子让我们认识了Binder通信机制不同于Linux的地方,还了解了用户空间和内核空间

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
千里马8年Android系统及应用开发经验,曾担任过美国unokiwi公司移动端技术总监兼架构师,对系统开发,性能优化,应用高级开发有深入的研究,Android开源定制ROM Lineage的贡献者之一,国内首家线下开辟培训Android Framework课程,拥有2年的Android系统培训经验。成为腾讯课堂专业负责android framework课程分享第一人,致力于提高国内android Framework水平Android Framework领域内是国内各大手机终端科技公司需要的人才,应用开发者都对Android系统充满着好奇,其中的binder是重中之重,都说无binderAndroidbinde是Android系统的任督二脉。课程水平循序渐进,由中级再到高级,满足各个层次水平的android开发者。1、灵活使用binder进程通信,在app端对它的任何api方法等使用自如2、可以单独分析android系统源码中任何binder部分,分析再也没有难度3、掌握binder驱动本质原理,及对应binder驱动怎么进行跨进程通信,及内存等拷贝方式数据等4、对binder从上层的java app端一直到最底层的内核binder驱动,都可以顺利理通5、针对系统开发过程中遇到的binder报错等分析方法,及binder bug案例学习6、针对面试官任何的binder问题都可以对答自如7、socket这种跨进程通信实战使用8、针对android源码中使用的socket源码轻松掌握9、android系统源码中最常见的socketpair中双向跨进程通信10、使用socket实现一个可以让app执行shell命令的程序

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值