跟面试官讲Binder(一)

跟面试官讲Binder(零) 通过上面的简单描述,我们可以这样认为,每一个提供服务的Server都会通过Binder驱动,将自身给注册到ServiceManager中,方便众多想获取服务的Client可以去ServiceManager找到自己。 那么,这些Service都会经过内核空间的Binder驱动,其实这个"经过"的说法,本质上,就是Server们会将自身作为一个对象,封装在数据包中,将这些数据复制到内核空间中,由Binder驱动访问。 而Binder驱动读取数据包的时候,如果发现其中有Binder实体,类似ServiceMana 阅读详情
面试官太忙了,过了好久之后,才想起我来,于是一个电话又把我叫过来了。
他说,想了解多一点关于Binder的知识。
心中一怔,其实对于Binder所知的其实也不多,但想着人家都问了,不随便说一点,这脸该往哪放呢?
琢磨一番,想着上一次讲的时候,有提到Binder中的通信的双方,一个叫server,一个叫client。
也就是说,Binder使用Client-Server的通信模式。
其中一个进程作为Server,多个进程作为Client,跨进程向Server获取服务。
我们可以联想到Web开发中的服务器设置,怎么知道是向哪个服务器中的哪个应用程序发送请求呢?
一个是ip地址,一个是端口号,如果服务器中有多个应用,我们还需要知道具体的应用名称呢,对吧。
简而言之,作为服务器,必须有确定的访问点或者地址来接受请求,比如我们上次说过了ServiceManager的句柄永远是0,这就是一个确定的访问点。

既然知道了对方在哪,Good,我们可以来通信了,那么问题来了,怎么通信?
跟英国人,美国人讲话,我们知道我们可以用英语,跟国人讲话,我们可以用普通话,跟家乡人,我们可以讲方言。
在网络上,这就是协议,规定了通信的规范和方式,比如 HTTP协议,我知道你用get就是想获得信息,用post就是想推送信息等。
很显然,在Binder机制中, 肯定也存在这样的协议和规范,来进行数据的通信。

上一篇文章中,我们讲到,在ServiceManager进程还不叫ServiceManager的时候,是通过 BINDER_SET_CONTEXT_MGR 命令来让其成为一个人人都要依靠的ServiceManager的。
而BINDER_SET_CONTEXT_MGR就是Binder机制中规范的的内容之一。
Binder制定Command-Reply协议,通过ioctl命令来跟驱动互动,告诉其什么样的命令去对数据进行怎么样的操作,如下:

#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, int64_t)
#define BINDER_SET_MAX_THREADS _IOW('b', 5, size_t)
#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, int)
#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, int)
#define BINDER_THREAD_EXIT _IOW('b', 8, int)
#define BINDER_VERSION _IOWR('b', 9, struct binder_version)

如我们讲过的 BINDER_SET_CONTEXT_MGR ,还有很重要的 BINDER_WRITE_READ 命令,大家都知道,肯定是关于读写的方面的命令的。
BINDER_WRIT_READ:往驱动写数据或者从驱动读数据,先写后读。单独写或者单独读,都是异步请求,如果同时有写读,则会是同步请求。
BINDER_SET_MAX_THREADS:告知驱动,接受方线程池的最大容量
BINDER_SET_CONTEXT_MGR:将当前进程设置为ServiceManager。在系统中只能有一个ServiceManager进程。
BINDER_THREAD_EXIT:通知驱动当前进程已退出。
BINDER_VERSION:获取当前驱动版本。
BINDER_WRITE_READ协议的格式(命令+数据)写

而对应的ioctl命令,主要以BC和BR开头,分别表示命令和返回结果的意思。
BinderCommand - BC
      BC_TRANSACTION = _IOW_BAD('c', 0, struct binder_transaction_data),
      BC_REPLY = _IOW_BAD('c', 1, struct binder_transaction_data),
      BC_REGISTER_LOOPER = _IO('c', 11),
      BC_ENTER_LOOPER = _IO('c', 12),
      BC_EXIT_LOOPER = _IO('c', 13),
BinderReply        - BR
      BR_ERROR = _IOR_BAD('r', 0, int),
      BR_OK = _IO('r', 1),
      BR_SPAWN_LOOPER = _IO('r', 13),
      BR_TRANSACTION = _IOR_BAD('r', 2, struct binder_transaction_data),
      BR_REPLY = _IOR_BAD('r', 3, struct binder_transaction_data),
      BR_TRANSACTION_COMPLETE = _IO('r', 6),

上面几个命令大概的作用如下:
往驱动写数据:
BC_TRANSACTION/ BC_REPLY等应该就是跟驱动进行数据交互的
BC_REGISTER_LOOP由Server方通知驱动线程池中已创建了一个新的线。
BC_ENTER_LOOP通知驱动此线程已经进入LOOP循环,能够接收数据。
BC_EXIT_LOOP通知驱动此线程已经退出LOOP循环,不再接收数据。

从驱动中读的数据格式
BR_NOOP
BR_ERROR / BR_OK
BR_SPAWN_LOOPER:驱动告知接收方没线程了,需要再创建,或者不再接收数据。
BR_TRANSACTION / BR_REPLY :对应于 BC_TRANSACTION / BC_REPLY
BR_TRANSACTION_COMPLETE,无论成功与否,驱动都会告知发送方的结果。

当然,如果想再了解得具体点,深入点,就需要好好地再看一下源代码了。此时,我偷偷看了一下面试官的表情,真让人敬畏啊。

我们可以看到其参数有 binder_transaction_data ,对吧,这肯定就是我们从用户空间写到内核空间,由驱动找到相对应的Server,处理好之后,返回来的结果呀。
下面就是binder_transaction_data的结构。
struct binder_transaction_data {
union {
size_t handle;
void *ptr;
} target;
void *cookie;
unsigned int code;

unsigned int flags;
pid_t sender_pid;
uid_t sender_euid;
size_t data_size;
size_t offsets_size;

union {
struct {

const void *buffer;

const void *offsets;
} ptr;
uint8_t buf[8];
} data;
};

在上面,我们可以看到一个union结构,一个是handle句柄, 一个是 *ptr指针。
在上一次面试中,已经讲过了,不同的进程间的引用叫句柄,相同进程中的引用,则称之为指针,也就是对进程空间中虚拟地址的引用。
当Client向Server发送请求的时候,它只知道Server是在另一个进程中,肯定没办法知道其对应的地址引用,它知道的只是ServiceManager告诉它的一个句柄而已。
而当驱动接到这个请求的时候,因为驱动是知道这个句柄对应的在另外一个进程(Server)中的引用的。所以会直接将handle替换成*ptr,让Server进程可以直接拿此*ptr来使用。

面试官估计听得有点不是很明白,为什么驱动会知道handle跟*ptr指针是互相对应的呢?
我深深觉得,我又发散了。。。收回来!
面试官的智慧是无穷的,他知道我上面讲了这么多,其实无非就是讲了两件事:
1)Binder是CS架构的,有对应的协议, 其中定义了众多的命令和数据结构来在不同的进程间传递数据。
2)在不同的进程间传递数据,是通过驱动的ioctl命令来对数据进行读写操作,也就是说,很多数据是在驱动中交互的。
但是,问题又来了,那到底整个过程是怎么样的呢,能不能具体点呢?

面试官好像要发火了,嗯,仔细再想想,怎么讲好?
Server和Client,那么肯定是先要有Server,才会有所谓的Client来请求的。
不对,之前应该先有ServiceManager的。
对,但是ServiceManager也是一个Server。
事情应该是这样的:
1)Server启动了,他要创建一个Binder实体,它的句柄是0,比如BpBinder(0),当设置了BINDER_SET_CONTEXT_MGR,驱动收到这个命令,它就知道是要将当前进程设置为ServiceManager,于是它就会当前这个Binder实体创建一个Binder节点(BinderNode),它在这里记录了 0 -> ServiceManager这样的mapping。
2)另一个Server启动了,它也会创建一个Binder实体,名字叫 XXXManagerService吧,但是它的句柄就不会是0了,是什么呢?不知道,当它这个Binder实体放到驱动中,驱动同时也会为其创建一个Binder节点,并且为其随机创建一个句柄,比如就叫 1 吧。
于是我们就知道在驱动中, 1 -> XXXManagerService的引用。
它进入驱动是为了寻找句柄0,去注册自己,也就是addService。
当然,驱动就会找到句柄0,发现其对应的是ServiceManager,就会将对应的数据,让ServiceManager来进行处理,这当然利用的就是内核空间的内存了。
在ServiceManager中,有一个服务列表svclist,保存了不同的服务名称对应的句柄,比如ServiceManager就会在自己的空间中保存这样一个对应  1-  > “XXXManagerService”。
OK,到这里,XXXManagerService就将自己注册到ServiceManager中了。
3)有一个Client也启动了,它要找XXXManagerService请求点资源,但是它只知道XXXManagerService的名字,而不知道其具体的句柄,不同进程之间,咫尺就是天涯啊。但是它知道有个叫ServiceManager的东西,它可能知道XXXManagerService在哪里,刚好,它知道它句柄就是0,于是它就去驱动中找一个句柄为0的,找到了,跟他通信,说它要找XXXManagerService,也就是findService。
刚好XXXManagerService注册了,ServiceManager就将其句柄传给了Client,现在Client终于知道XXXManagerService的地址(句柄)了,于是它就又重新包装好数据,这次的句柄就不是0了,而是 1 了,又一头扎进驱动了,继续做该做的事情。

这样说得好像挺形象的,面试官好像也听明白了,表情挺精彩的。

好吧,就再给个图吧,希望能够给面试官点印象分。


面试官看完之后,依然面无表情,我好捉急,这到底是怎么样啊?结合上面讲的,这个图应该还是可以理解的吧,可能是画功太烂了。

【安卓源码】Binder机制3 -- Binder线程池 Binder本身是C/S架构,就可能存在多个Client会同时访问Server的情况。在这种情况下,如果Server只有一个线程处理响应,就会导致客户端的请求可能需要排队而导致响应过慢的现象发生。解决这个问题的方法就是引入多线程。【多个客户端不同线程去请求,服务端需要使用多线程机制,binder线程池,创建多个线程去回复多个客户端的请求】Binder机制的设计从最底层–驱动层,就考虑到了对于多线程的支持。 阅读详情

相关推荐

Android Binder进程间通信机制

1 Binder机制简介 为了系统的安全与稳定,Linux系统是存在进程隔离的:两个不同的进程,如应用App进程和ActivityManagerService服务所在的system_server系统进程,是无法直接通过内存地址访问到对方内部的函数或者变量的。所以两个进程如果需要相互访问就涉及到一个跨进程通信的概念即IPC(Inter-process communication,进程间通讯)。本质上是借助于不同进程的内核空间都是共享的原理,两个不同的进程都去访问内核空间,从而达到“间接”访问对方的目的。Bin

鸿蒙开发知识记录 1936

梳理binder通信流程(binder驱动部分)

在android系统中,与binder打交道是避不开的,因此需要了解binder通信流程。但是binder通信流程比较复杂、涉及模块比较多,很难短时间内把binder通信原理全部搞清楚。网上很多介绍binder通信的文章,一方面年代久远(大多都是5-10年前),虽说binder整个框架没有变,但是其中一些技术细节以及代码是有所变化的;

weixin_44088874的博客 3067

跟面试官讲Binder(二)之关于AIDL的认识

面试官开口说:“听你刚才所说,在Android系统中,都是利用Binder来进行进程间通信的,那我怎么听说,还有利用AIDL来实现进程间通信的呢?”。 其实,AIDL只是一种描述性语言,其全称是Android Interface Definition Language,即接口定义语言,利用ADT,我们可将自定义的AIDL文件转化成Java代码,而这些代码就能够来进行进程间通信(IPC)。为什么这些代码就能够进行IPC呢?那是因为,这些代码就是定义了Binder机制中作为服务端的Binder对象和客户端中用的

持剑 5322

Android跨进程通信二

1. Binder是什么 从机制上来说: Binder是Android中一种跨进程通信的方式 从Binder机制实现来说: Binder是一种虚拟的物理设备驱动 从Java层面来说: Binder是一个类,实现了IBinder接口。 2. Binder机制 2.1 背景知识 2.1.1 进程空间划分 一个进程空间分为 用户空间 & 内核空间(Kernel),即把进程内 用户 & 内...

吓成一坨兔子 3123

征服面试官:Binder 原理篇 掌握这篇面试题汇总,吊打面试官!

Binder 是 Android 中的一种跨进程通信方式。从 Android Framework 角度来说 Binder 是 ServiceManager 连接各种 Manager(ActivityManager、WindowManager 等等)和相应 ManagerService 的桥梁;从 Android 应用层来说 Binder 是客服端与服务端进行通信的媒介。 1、什么是 Binder? 直观来说,Binder 是 Android 中的一个类,它继承了 IBinder 接口 从 IPC 角度来说

一名互联网时代苟且偷生的 Android码农 3189

腾讯面试官:Binder的系统服务是如何获取的?

本文首发于微信公众号「后厂村码农」 关联系列 Android AOSP基础系列 Android系统启动系列 应用进程启动系列 Android深入四大组件系列 Android深入理解Context系列 Android深入理解JNI系列 Android解析WindowManager Android解析WMS系列 Android解析AMS系列 Android包管理机制系列 Android输入系统系列...

Android进阶三部曲 - 刘望舒 1915

腾讯面试官——说说你对 binder 驱动的了解?

作者:Android面试官 原文地址:https://juejin.im/post/5eeea016e51d45740e4273e8 面试官提了一个问题:说说你对 binder 驱动的了解。这个问题虽有些 "面试造火箭" 的无奈,可难点就是亮点、价值所在,是筛选面试者的有效手段。如果让你回答,你能说出多少呢?我们来看看 ????、???? 和 ????️ 三位同学的回答如何吧 ???? 自认为无所不知,水平已达应用开发天花板,目前月薪 10k 面试官️:说说你对 binder 驱动的了解 ??

鸿蒙开发知识记录 6310

电动汽车欧标直流充电标准解析

电动汽车和电动汽车充电市场是动态发展的,欧洲也正在努力部署基础设施,以支持欧洲快速增长和多样化的电动汽车充电需求。

网络安全的研究者、新能源行业的追求者 7617

大厂Android面试官亲讲:Binder 相关问题到底该怎样回答

我的一个朋友在某互联网大厂(Alibaba)的Android开发岗工作了五年,最近几次奉命去当面试官,面了不少应聘者,这是他吐槽的发生在面试中的一些事情。 原文地址:大厂Android面试官亲讲:Binder 相关问题到底该怎样回答 背景 我们搞技术的也没什么别的人脉圈子,平时也就哥几个吃个饭,喝个酒,吹个牛逼。 前阵子几个朋友小聚,大家喝了点酒就开始吹牛逼,他一边感叹了一下现在越来越少的休息时间一边说老板为什么还不给他转岗的机会,说着说着就开始感慨新来的那些员工。 “现在的这些应聘者,学历工作经验看着.

BUGgogogo的博客 391

Xiaojie雷达之路---毫米波雷达基础知识---角度估计

本篇文章主要介绍毫米波雷达的基础知识中的角度估计,对于本篇文章主要回答5个问题 1.在雷达的前方,如何估计前方一个物体的角度 2.角度测量的准确性 3.如何测量多个物体的角度 4.雷达可测的角度的视场最大值为多少 5.角度分辨率取决于什么因素 文章目录估计雷达前面一个物体的角度角度测量的准确性雷达的最大角视场测量雷达前方多个距离和速度相同的物体角度分辨率角度估计的流程 估计雷达前面一个物体的角度 估计一个物体的角度,最少需要两根接收天线 发射天线发送一个chirp,经过物体发射后信号,信号分别被第一根天

XiaoJie的博客 1万+

MDK5 Debug调试方法总结

MDK5 Debug调试方法总结

m0_70748084的博客 2万+

Android面试官:说说你对 Binder 驱动的了解?

🤔️:简单画张图吧:对 Binder 机制来说,它是 IPC 通信的路由器,负责实现不同进程间的数据交互,是 Binder 机制的核心;对 Linux 系统来说,它是一个字符驱动设备,运行在内核空间,向上层提供 /dev/binder 设备节点及 open、mmap、ioctl 等系统调用。:你提到了驱动设备,那先说说 Linux 的驱动设备吧🤔️:Linux 把所有的硬件访问都抽象为对文件的读写、设置,这一"抽象"的具体实现就是驱动程序。

2401_84544714的博客 480

语音增强评价指标全解析:从MOS到eSTOI的实战指南

本文全面解析了语音增强领域的核心评价指标,包括主观评价的黄金标准MOS,以及PESQ、STOI、eSTOI等关键客观指标。文章详细阐述了各指标的原理、适用场景与实战计算方法,并提供了Python代码示例,旨在帮助开发者和研究者建立科学的评估体系,以平衡语音可懂度与音质,从而优化算法效果。

yhn456789的博客 1199

Android面试官:说说你对 Binder 驱动的了解?,android开发基础学习

简历首选内推方式,速度快,效率高啊!然后可以在拉钩,boss,脉脉,大街上看看。简历上写道熟悉什么技术就一定要去熟悉它,不然被问到不会很尴尬!做过什么项目,即使项目体量不大,但也一定要熟悉实现原理!不是你负责的部分,也可以看看同事是怎么实现的,换你来做你会怎么做?做过什么,会什么是广度问题,取决于项目内容。但做过什么,达到怎样一个境界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。

2301_77118221的博客 1032

Android11 关于三方应用获取su权限

SELinux,全称Security-Enhanced Linux,是一种基于Linux内核的安全机制。它通过强制访问控制(MAC)来增强Linux系统的安全性,如果不禁用SELinux,完成下面的修改可能会导致设备进入Recovery界面!adb shell getenforce 为Permissive(宽容模式),查看报错日志,发现是客户apk想使用su命令提权,但是没有权限!对于保护系统资源和防止未经授权访问非常有帮助!系统这边做修改,让su权限下放到三方应用.客户的apk运行报错。

sinat_37429535的博客 1901

《网络安全自学教程》- Windows基线检查加固

Windows安全配置,基线检查标准,基线加固方式

wangyuxiang946的博客 1万+

当面试官问到Binder这些问题,你会怎么答?

直接让我说了解不好回答啊,还是问我问题吧:好,你刚才提到了系统内核,那介绍一下用户空间和内核空间吧:不知道,这东西了解了也没什么用啊!我对业务开发 API 比较了解,比如 RecycleView 布局,我写的贼溜~:好的,回去等通知吧:说说你对 binder 驱动的了解:binder 机制分为四部分,binder 驱动、Service Manager、客户端、服务端。

2401_84048161的博客 767

C# HttpClient完全攻略:从入门到精通只需5步

HttpClient是.NET框架中用于发送HTTP请求和接收HTTP响应的类。它基于异步编程模型,使得网络操作更加高效和灵活。

java专栏 1579

Android面试官:说说你对 Binder 驱动的了解?,android开发者选项说明

????️:binder 机制将业务细分为不同的命令,调用 binder_ioctl() 时传入具体的命令来区分业务,比如有读写数据的 BINDER_WRITE_READ 命令、 Service Manager 专用的注册为 DNS 的命令等等。 BINDER_WRITE_READ 命令最为关键,其细分了一些子命令,比如 BC_TRANSACTION、BC_REPLY 等。BC_TRANSACTION 就是上层最常用的 IPC 调用命令了,AIDL 接口的 transact 方法就是这个命令。 面试官:bi

m0_63935510的博客 769

SAP-MM:SAP MM(物料管理)模块 的系统化学习计划

SAP MM模块的系统化学习计划

baidu_35680696的博客 1547

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

上一篇: 关于ThreadLocal的一些认识
下一篇: Android学习小Demo(22)带删除按钮的TextView
linmiansheng
博客等级 码龄20年 507粉丝 111原创
评论 11
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值