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将执行结果从内核空间复制到用户空间。并唤醒等待的线程,相应结果。

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
份全套学习资料的朋友可以戳我获取!!**](https://bbs.youkuaiyun.com/topics/618165277)

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值