binder机制再学习

binder有四个主角分别为:Server 、Client (不难理解,因为是基于C/S模式)

ServiceManger 、 Binder驱动。

前三者都作用于用户空间,而Binder驱动作用于内核空间。

这个时候引出用户空间及内核空间的概念,接下来通过一张图来理解这两个概念:

在这里插入图片描述

看图说话:每个Android进程包含两个空间,一个是内核空间(占用空间少的),特点是不同进程的内核空间是可以共享的,而用户空间的资源是不可以共享的。

我们不同进程要通信的资源肯定都在用户空间啦~所以这个时候就要利用内核空间中的Binder驱动来管理。用户空间通过ioctl等方法来和内核空间通信。

1. Binder驱动

虽然叫“驱动”,但是和硬件驱动没有任何关系,只是作用和驱动差不多。作用于内核态(内核空间),主要负责进程间Binder通信的建立、Binder在进程间的传递、Binder引用计数的管理、数据包在进程间传递和交互的一系列底层支持。

用户态和内核态是隔离开的,但我们用户态也要访问内核态呀,这个时候用户态访问内核态的唯一空间就是系统调用;通过这个统一入口接口,然后所有的资源访问都是在内核的控制下执行,以免导致对用户程序对系统资源的越权访问,从而保障了系统的安全和稳定。在执行内核态的方法是优先级是0(最高)可以使用CPU特殊的优先方法,而用户态则是3(最低)。

Binder 并不是 Linux 内核的一部分,它是怎么做到访问内核空间的呢? Linux 的动态可加载内核模块(Loadable Kernel Module,LKM)机制解决了这个问题;模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行。这样,Android系统可以通过添加一个内核模块运行在内核空间,用户进程之间的通过这个模块作为桥梁,就可以完成通信了。

熟悉了上面的概念可以来看看下图:

在这里插入图片描述

用户态中的binder_open()、binder_mmap()、binder_ioctl()就是通过调用System call来调用内核态中的方法。用户态和内核态中的共享内存由内核态来调用copy_from_user和copy_to_user来传输。

Binder驱动中保存了一个binder_procs的全局链表来保存服务端的进程信息。

Binder进程和线程

对于底层Binder的驱动,底层的binder_procs链表就记录着所有创建了binder_proc的结构体,每一个binder_proc结构体都与一个用于binder通信的进程对应,每个进程通过单例模式保证自己唯一的ProcessState对象,每个线程也有自己的IPCThreadState对象(也是单例模式保证唯一),在Binder驱动层也有和它对应的Binder_thread,binder_proc结构体中的rb_root threads就是记录自己进程中的所有线程的Binder_thread,具体看下图:

在这里插入图片描述

2. ServiceManager

ServiceManager是Binder驱动的守护进程,其实作用简化来说就是提供了 查询服务 和 注册服务的功能。

下面介绍ServiceManager主要分成三部分,分别为启动、注册服务、获取服务。

首先是ServceManger的启动,看下图:在这里插入图片描述

(1)ServiceManager分为framework层和native层,framework层只是对native层进行了封装,方便调用,图上展示的是native层的SM启动过程。

(2)ServiceManager的启动是系统在开机时,init进程解析了init.rc文件调用了 service_manager.c中的main()方法入口启动的 。native层有一个binder.c封装了一些与Binder驱动交互的方法。

(3)ServieceManager启动分为三步:首先打开驱动创建全局链表binder_procs,然后将自己的ProssStats包装成一个binder_proc插入到链表中,最后开启loop循环不断处理共享内存中的数据,并处理BR_xxx命令(ioctl的命令,BR可以理解为binder reply驱动处理完的相应)

其次是ServiceManager的注册

在这里插入图片描述

(1)比如说我们要注册一个服务端,我们就要通过ServiceManager的addService来实现。

(2)首先ServiceManager向Binder驱动发送BC_TRANSACTION命令(ioctl的命令,BC可以理解为binder client发送过来的请求)携带了ADD_SERVICE_TRANSATION命令,同时注册服务的线程进入等待状态 waitForResponse()。Binder驱动收到请求命令向ServiceManager的todo队列里添加一条事务。接着事务就创建服务进程的binder_porc并插入到链表中。

(3)Binder驱动处理完BR_TRANSATION后会通知ServiceManager,SM接着就像svcinfo中添加已经注册的服务。最后发送BR_REPLY命令唤醒等待的线程,通知注册成功。

ServiceManager获取服务:

在这里插入图片描述

看的出来其实获取服务和注册服务类似,不过是通过相反的过程。

(1)通过ServiceManager的getService()方法来注册服务。

(2)首先ServiceManager向Binder驱动发送BC_TRANSACTION,命令携带CHECK_SERVICE_TRANSACTION,同时获取服务的线程进入等待态

(3)Binder接到BC_TRANSACTION就会查询binder_procs中是否存在注册的服务,如果存在则立即通过BR_REPLY唤醒等待线程。若查询不到则通过binder_procs中的服务进行一次通讯再响应。

3. 进行一次完整通讯

在这里插入图片描述

(1)我们在使用Binder时基本调用的都是framework封装好的方法。AIDL就是framework层提供的傻瓜式的使用方法。

(2)如果服务注册好了,我们就通过ServiceManager获取服务端的代理对象BinderProxy,通过调用参数(TRANSATION_test,AIDL中自动生成)传给ServiceManager,同时客户端进入等待状态

(3)ServiceManager将用户空间的参数等请求复制到内核空间,并向服务端插入一条执行事务的方法。事务执行完通知ServiceManager将执行结果从内核空间复制到用户空间。并唤醒等待的线程,相应结果。

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

上面分享的腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

【Android高级架构视频学习资源】

Android部分精讲视频领取学习后更加是如虎添翼!进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》
点击传送门,即可获取!

进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 18
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值