Binder常见面试题

1,055 阅读5分钟

1、Binder有什么优势?

IPC通信有以下几种方式,Socket 共享内存 BInder,我会从安全性、易用性、资源消耗几个角度来进行分析

Socket

1、不安全,依赖上层协议,访问接入点开放

2、基于C/S架构,控制容易,作为通用接口效率低,开销大。

3、2次拷贝。为什么两次拷贝呢?因为socket通讯可能不在一台设备上,比如手机通过socket通讯访问电脑。

共享内存

1、不安全,依赖上层协议,访问接入点开放

2、控制复杂,易用性差

3、0拷贝

Binder 1、安全为每个App分配UID,同时支持实名和匿名

2、基于C/S架构,易用

3、1次拷贝

2、Binder是怎么做到一次拷贝的?

这里涉及到一个概念叫内存映射mmap,在内核空间和用户空间使用物理地址开辟了一个映射关系。 内核空间调用copy_from_user会将数据直接拷贝到内核空间并反馈映射到物理地址上 由于用户空间和物理地址有一个映射关系,用户空间可以直接通过映射的虚拟地址指针访问当写入物理地址的数据。

3、mmap的原理讲解

Linux通过一个虚拟内存空间区域与一个磁盘上的对象关联起来,以初始化这个虚拟内存区域的内容,这个过程称为内存映射(memory mapping)

对文件进行mmap,会在进程的虚拟内存分配地址空间,创建映射关系。

实现映射关系后,就可以采用指针的方式读写操作这一段内存,而系统会自动会写到对应文件磁盘上

所有的系统资源管理都是在内核空间完成的,比如读写磁盘文件,网络接口读写。 用户空间通过系统调用让内核空间完成这些功能。

image.png

mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。使进程可以直接访问文件的内容,避免频繁读写,也可以实现进程间通信。

完成映射关系之后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页到对应的文件磁盘上,完成对文件操作而不必调用read write。

3.1进程启动映射过程,并在虚拟地址空间中为映射创建虚拟映射区域

3.2调用内核空间的系统调用函数mmap(不同于用户空间函数),实现文件物理地址和进程虚拟地址的一一映射关系

3.3进程发起对这片映射空间的访问,引发缺页异常,实现文件内容到物理内存(主存)的拷贝

4、binder机制是如何跨进程的??

Binder IPC机制中涉及到mmap()来实现,就是将用户空间中的一块内存映射到内核空间,映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间,反之亦可。

且内核空间是可以相互访问的。

两个进程对应两个空间,各自的修改能直接反映在映射的内存区域,从而被对方的空间即使感知。因此,内存映射能够支持进程间通信。

5、AIDL生成java类的细节

会生成一个接口声明通信协议、一个代理对象Proxy(客户端用)、一个Stub 服务端使用(00:23~40)

当客户端binderService时,会回调一个onServiceConnected,其中会通过Stub.asInterface() 来获取代理对象。

asInterface会区分是跨进程还是非跨进程中,如果是跨进程则返回代理对象,如果不是跨进程就返回服务端。

拿到代理对象之后就会调用接口方法proxy.XXX(),接口方法里边,首先会打两个包,一个包是我们传入数据包,一个是返回数据包。再做个安全检查。然后调用mRemoute.transact(),其中flag为0表示同步(1M-8k)一般传的数据没有这么多,因为包也占空间,1表示异步只有一半。从客户端跑到服务端,其中会用到serviceManager。

服务端会跑Stub中的onTransact()方法,调用方法这里做了一个优化,不用全类名,直接将方法转为数字,再Stub中有常量数字。传个int,再switch查。确定是调用哪个方法之后,进行解包,然后调用this.XXX()。如果有结果则会回写。把结果写进reply包里。this.XXX()则会调用到RemoteService里边。这样就从客户端跑到服务端。

6、四大组件底层通信机制

客户端进程与ServiceManager通信获得AMS的IBinder

客户端通过AMS的IBinder与AMS通信,请求bindService。

AMS会调用scheduleBindService()之后会调用handleBindService()。 首先从mService.get(data.token)中拿到service对象,这个service对象就是remouteService,这个service是通过反射创建的,将其放在Map集合中。 拿出的service调用onBind拿到IBind对象。

通过AMS将publicService将binder返回,最终调用到客户端的ServiceConnection的OnServiceConnected。这样就把IBinder对象传过来了。然后Stub.asInterface(service)拿到代理对象。然后调用代理对象的xxx()方法。

这个就是四大组件通信,其实就是用的binder。

image.png

7、Intent为什么不能传递大数据

Intent携带信息的大小受Binder限制,数据以Parcel对象的形式存放在Binder传递缓存中,而binder传递数据最大为1M-8K,如果过大则传递失败并抛出TransactionTooLargeException异常。