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

莎利亚 等级 626 0 0

我的一个朋友在某互联网大厂(Alibaba)的Android开发岗工作了五年,最近几次奉命去当面试官,面了不少应聘者,这是他吐槽的发生在面试中的一些事情。

背景

我们搞技术的也没什么别的人脉圈子,平时也就哥几个吃个饭,喝个酒,吹个牛逼。

前阵子几个朋友小聚,大家喝了点酒就开始吹牛逼,他一边感叹了一下现在越来越少的休息时间一边说老板为什么还不给他转岗的机会,说着说着就开始感慨新来的那些员工。

“现在的这些应聘者,学历工作经验看着还亮眼,结果一问三不知。”他一脸吃到了苍蝇的表情“上次我们公司来了个211硕士学历的,简历上写着熟知底层,也做了不少项目,结果我问了个Binder 层的问题都讲不明白,真的是浪费时间,还不如回家先学好了再来……”

我想了下自己最近面试的那些新人,简历上一看,个个都是人才精英,学历有了很大的提升,一拿出来,什么985,211的不少,要么就是做过很多大项目的大佬,但是底层原理很多人也讲不出个所以然。

今天在这里就专门开文写一下这个知识点,希望在即将到来的“金三银四”面试季中对大家有所帮助。

前言

理解Binder对于理解整个Android系统有着非常重要的作用,Android系统的四大组件,AMS,PMS等系统服务无一不与Binder挂钩;如果对Binder不甚了解,那么就很难了解这些系统机制,从而仅仅浮游与表面,不懂Binder你都不好意思说自己会Android开发;要深入Android,Binder是必须迈出的一步。

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

在Android开发过程中,Binder的身影无处无处不在,我们编写的程序都使用过Binder机制(例如startActivity的执行过程)但是请问你知道什么是Binder么?在开发过程中你察觉到它的存在了么?Biner翻译过来是“胶水“的意思,这个翻译分形象。Binder的主要工作就是淡化了进程边界,淡化了进程间通信的过程。要是想更好的理解Binder就必须从Linux进程谈起。

Linux进程

为了保护进程空间不被别的进程破坏或者干扰,Linux中的进程是相互独立的,也就是所谓的进程隔离。(而且一个进程的内存空间还被分为了用户空间和内核空间,二者也是相互隔离的。这里不做探讨)所以在Linux中,进程与进程之间是相互隔离的,而且进程中的用户和内核空间也是隔离的。

也就是说为了安全和独立,一个进程是不能直接操作或者访问另外一个进程的内存空间的。他们之间既然是隔离的,在需要通信、协作的时候就需要使用进程间通信技术(即IPC,也称跨进程通信),我们都知道Android框架是建立在Linux之上的,当然也会面对进程间通讯的问题。

为什么使用Binder

在Linux系统中为了达到进程间通讯的目的,我们可以选用诸如管道、Socket等技术手段,那么为什么Android选用了Binder这种新型的IPC技术,放弃了原有成熟的技术呢?

主要有如下两个方面:

1.性能角度

由于在移动设备诸如省电等性能的考虑,广泛地使用进程间通讯对于通信机制的性能有严格的要求,Binder相对于传统的Socket、管道方式更加高效。Bidner数据拷贝只需要一次,而管道、消息队列、Socket都需要2次,内存共享方式一次内存拷贝都不需要,但是实现起来难度高,复杂性大。

2.稳定性角度

传统的进程通信方式对于通信双方的身份并没有做出严格的验证,比如Socket通信ip地址是客户端手动填入,很容易进行伪造,而Binder机制从协议本身就支持对通信双方做身份校检,因而大大提升了安全性。

Binder机制

一、Binder通信概述

binder通信是一种client-server的通信结构。

1.从表面上来看,是client通过获得一个server的代理接口,对server进行直接调用;

2.实际上,代理接口中定义的方法与server中定义的方法是一一对应的;

3.client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成为Parcel对象;

4.代理接口将该Parcel发送给内核中的binder driver.

5.server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回;

6.整个的调用过程是一个同步过程,在server处理的时候,client会block住。

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

二、service manager

Service Manager是一个linux级的进程,顾名思义,就是service的管理器。这里的service是什么概念呢?这里的service的概念和init过程中init.rc中的service是不同,init.rc中的service是都是linux进程,但是这里的service它并不一定是一个进程,也就是说可能一个或多个service属于同一个linux进程。在这篇文章中不加特殊说明均指android native端的service。

任何service在被使用之前,均要向SM(Service Manager)注册,同时客户端需要访问某个service时,应该首先向SM查询是否存在该服务。如果SM存在这个service,那么会将该service的handle返回给client,handle是每个service的唯一标识符。

SM的入口函数在service_manager.c中,下面是SM的代码部分:

int main(int argc, char **argv){struct binder_state *bs;void *svcmgr = BINDER_SERVICE_MANAGER;bs = binder_open(128*1024);if (binder_become_context_manager(bs)) {LOGE(“cannot become context manager (%s)/n”, strerror(errno));return -1;}svcmgr_handle = svcmgr;binder_loop(bs, svcmgr_handler);return 0;} 

这个进程的主要工作如下:

1.初始化binder,打开/dev/binder设备;在内存中为binder映射128K字节空间;

2.指定SM对应的代理binder的handle为0,当client尝试与SM通信时,需要创建一个handle为0的代理binder,这里的代理binder其实就是第一节中描述的那个代理接口;

3.通知binder driver(BD)使SM成为BD的context manager;

4.维护一个死循环,在这个死循环中,不停地去读内核中binder driver,查看是否有可读的内容;即是否有对service的操作要求, 如果有,则调用svcmgr_handler回调来处理请求的操作。

5.SM维护了一个svclist列表来存储service的信息。

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

这里需要声明一下,当service在向SM注册时,该service就是一个client,而SM则作为了server。而某个进程需要与service通信时,此时这个进程为client,service才作为server。因此service不一定为server,有时它也是作为client存在的。

三、ProcessState

ProcessState是以单例模式设计的。每个进程在使用binder机制通信时,均需要维护一个ProcessState实例来描述当前进程在binder通信时的binder状态。

ProcessState有如下2个主要功能:

1.创建一个thread,该线程负责与内核中的binder模块进行通信,称该线程为Pool thread;

2.为指定的handle创建一个BpBinder对象,并管理该进程中所有的BpBinder对象。

(一)Pool thread

在Binder IPC中,所有进程均会启动一个thread来负责与BD来直接通信,也就是不停的读写BD,这个线程的实现主体是一个IPCThreadState对象,下面会介绍这个类型。

下面是 Pool thread的启动方式:

ProcessState::self()->startThreadPool();

(二) BpBinder获取

BpBinder主要功能是负责client向BD发送调用请求的数据。它是client端binder通信的核心对象,通过调用transact函数向BD发送调用请求的数据,它的构造函数如下:

BpBinder(int32_t handle);

通过BpBinder的构造函数发现,BpBinder会将当前通信中server的handle记录下来,当有数据发送时,会通知BD数据的发送目标。

ProcessState通过如下方式来获取BpBinder对象:

ProcessState::self()->getContextObject(handle); 

在这个过程中,ProcessState会维护一个BpBinder的vector mHandleToObject,每当ProcessState创建一个BpBinder的实例时,回去查询mHandleToObject,如果对应的handle已经有binder指针,那么不再创建,否则创建binder并插入到mHandleToObject中。

ProcessState创建的BpBinder实例,一般情况下会作为参数构建一个client端的代理接口,这个代理接口的形式为BpINTERFACE,例如在与SM通信时,client会创建一个代理接口BpServiceManager。

四、IPCThreadState

IPCThreadState也是以单例模式设计的。由于每个进程只维护了一个ProcessState实例,同时ProcessState只启动一个Pool thread,也就是说每一个进程只会启动一个Pool thread,因此每个进程则只需要一个IPCThreadState即可。

Pool thread的实际内容则为:

IPCThreadState::self()->joinThreadPool(); 

ProcessState中有2个Parcel成员,mIn和mOut,Pool thread会不停的查询BD中是否有数据可读,如果有将其读出并保存到mIn,同时不停的检查mOut是否有数据需要向BD发送,如果有,则将其内容写入到BD中,总而言之,从BD中读出的数据保存到mIn,待写入到BD中的数据保存在了mOut中。

ProcessState中生成的BpBinder实例通过调用IPCThreadState的transact函数来向mOut中写入数据,这样的话这个binder IPC过程的client端的调用请求的发送过程就明了了。

IPCThreadState有两个重要的函数,talkWithDriver函数负责从BD读写数据,executeCommand函数负责解析并执行mIn中的数据。

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

五、主要基类

(一)基类IInterface

为server端提供接口,它的子类声明了service能够实现的所有的方法;

(二)基类IBinder

BBinder与BpBinder均为IBinder的子类,因此可以看出IBinder定义了binder IPC的通信协议,BBinder与BpBinder在这个协议框架内进行的收和发操作,构建了基本的binder IPC机制。

(三)基类BpRefBase

client端在查询SM获得所需的的BpBinder后,BpRefBase负责管理当前获得的BpBinder实例。

最后

Android学习是一条漫长的道路,我们要学习的东西不仅仅只有表面的 技术,还要深入底层,弄明白下面的 原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足。

本文在开源项目:我的GitHub
中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中...

这次就分享到这里吧,下篇见

本文转自 https://www.jianshu.com/p/5cabe499922c,如有侵权,请联系删除。

收藏
评论区

相关推荐

Android深入浅出之Binder机制
Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的。所以搞明白Binder的话,在很大程度上就能理解程序运行的流程。 我们这里将以MediaService的例子来分析Binder的使用: ServiceMan
大厂Android面试官亲讲:Binder 相关问题到底该怎样回答
我的一个朋友在某互联网大厂(Alibaba)的Android开发岗工作了五年,最近几次奉命去当面试官,面了不少应聘者,这是他吐槽的发生在面试中的一些事情。背景我们搞技术的也没什么别的人脉圈子,平时也就哥几个吃个饭,喝个酒,吹个牛逼。前阵子几个朋友小聚,大家喝了点酒就开始吹牛逼,他一边感叹了一下现在越来越少的休息时间一边说老板为什么还不给他转岗的机会,
Android应用程序进程启动过程(后篇)
本文首发于微信公众号「后厂技术官」 前言在前篇中我们讲到了Android应用程序进程启动过程,这一篇我们来讲遗留的知识点:在应用程序进程创建过程中会启动Binder线程池以及在应用程序进程启动后会创建消息循环。<more 1.Binder线程池启动过程我们首先来看RuntimeInit类的zygoteInit
Android Binder原理(一)学习Binder前必须要了解的知识点
本文首发于微信公众号「刘望舒」 前言Binder原理是掌握系统底层原理的基石,也是进阶高级工程师的必备知识点,这篇文章不会过多介绍Binder原理,而是讲解学习Binder前需要的掌握的知识点。 1.Linux和Android的IPC机制种类IPC全名为interProcess Communication,含义为进程间
Android Binder原理(二)ServiceManager中的Binder机制
Binder原理 Android框架层本文首发于微信公众号「刘望舒」<more 前言在上一篇文章中,我们了解了学习Binder前必须要了解的知识点,其中有一点就是Binder机制的三个部分:Java Binder、Native Binder、Kernel Binder,其中Java Binder和Native
Binder Driver缺陷导致定屏的案例
本文讲解异步binder call是如何阻塞整个系统的,通过ramdump信息以及binder通信协议来演绎并还原定屏现场。 一、背景知识点解决此问题所涉及到的基础知识点有:Trace、CPU调度、Ramdump推导、Crash工具、GDB工具、Ftrace, 尤其深入理解binder IPC机制。 1.1 工具简介 Trace:分析死锁
Android 操作系统架构开篇
版权声明: 本站所有博文内容均为原创,转载请务必注明作者与原文链接,且不得篡改原文内容。为便于日常查阅本博客,可通过 方便检索文章 一、引言众所周知,Android是谷歌开发的一款基于Linux的开源操作系统,从诞生至今已有10余年,这一路走来Android遇到哪些问题?大版本升级朝着什么方向演进?Android的未来如何?我的公号 讲解了Android一
Android四大组件与进程启动的关系
一. 概述Android系统将进程做得很友好的封装,对于上层app开发者来说进程几乎是透明的. 了解Android的朋友,一定知道Android四大组件,但对于进程可能会相对较陌生. 一个进程里面可以跑多个app, 一个app也可以跑在多个进程里,通过配置Android:process属性来决定所运行在哪个进程。再进一步进程是如何创建的, 可能很多人不知道f
Android Binder原理(三)系统服务的注册过程
Binder原理 Android框架层本文首发于微信公众号「刘望舒」<!more 前言在上一篇文章中,我们学习了ServiceManager中的Binder机制,有一个问题由于篇幅问题没有讲完,那就是MediaPlayerService是如何注册的。通过了解MediaPlayerService是如何注册的,可以得知系统服务的注册过程。 1.从调用链角度说明M
Android应用启动速度优化
应用启动流程总结: ①点击启动一个App,Launcher进程采用Binder IPC向ActivityManagerService发起startActivity请求; ②ActivityManagerService接收到请求后,向zygote进程发送创建进程的请求; ③Zygote进程fork出新的子进程,即App进程; ④App进程通过Bin
Android Binder原理(四)ServiceManager的启动过程
Binder原理 Android框架层本文首发于微信公众号「刘望舒」<!more 前言在上一篇文章中,我们以MediaPlayerService为例,讲解了系统服务是如何注册的(addService),既然有注册就势必要有获取,但是在了解获取服务前,我们最好先了解ServiceManager的启动过程,这样更有助于理解系统服务的注册和获取的过程。另外还有一点
Android Binder原理(五)系统服务的获取过程
Binder原理 Android框架层本文首发于微信公众号「后厂技术官」<!more 前言在本系列的此前文章中,以MediaPlayerService为例,讲解了系统服务是如何注册的(addService),既然有注册那肯定也要有获取,本篇文章仍旧以MediaPlayerService为例,来讲解系统服务的获取过程(getService)。文章会分为两个部分
Android Binder原理(六)Java Binder的初始化
Binder原理 Android框架层本文首发于微信公众号「刘望舒」<!more 前言在这篇文章中,我根据Android系统的分层,将Binder机制分为了三层:1. Java Binder (对应Framework层的Binder)2. Native Binder(对应Native层的Binder)3. Kernel Binder(对应Kernel层的Bi
Android Binder原理(七)Java Binder中系统服务的注册过程
Binder原理 Android框架层本文首发于微信公众号「后厂技术官」<!more 前言在这篇文章中,我介绍的是Native Binder中的系统服务的注册过程,这一过程的核心是ServiceManager,而在Java Binder中,也有一个ServiceManager,只不过这个ServiceManager是Java文件。既然要将系统服务注册到Ser
JNI 基础 - Android 共享内存的序列化过程
1. 进程间的通信方式有哪些2. binder 和 socket 通信的区别有哪些3. Android 为什么在大部分场景下用 Binder 进行进程间通信4. Serializable 和 Parcelable 之间的区别5. Parcelable 序列化和反序列化的具体过程不知道大家在面试中的过程中,有没有碰到上面类似的问题,我在腾讯和 oppo 面试的