Android 面试笔记之Binder详解

Android 面试笔记之Binder详解

Binder 八问

1.为什么面试要问Biner?

1.1 Binder是什么?

Activity, Service等组件都需要和AMS 进行交互,这些跨进程的通信都是 通过 Binder来完成的。

三种角度看待Binder:
	机制:一种跨进程通信的机制

	驱动:虚拟物理设备驱动

	应用层:Binder是一个能发起通信的Java类

1.2 为什么要使用多进程?

1.2.1 因为虚拟机分配给各个进程的内存是有限制的,可以突破 内存限制

为什么现在的机器最大内存已经有16G了,但是你加载某个大图的时候,还是会OOM,就是因为 虚拟机分配给每个进程的内存是有限制的

1.2.2 独立的进程 有助于 保持长连接的稳定性 (推送)

1.2.3 规避内存泄漏:独立的webview进程 阻隔内存泄漏导致的问题

1.2.4 隔离风险,对于不稳定的功能单独进程运行,避免主进程 崩溃

1.3 系统服务 输入法,闹钟,短信,电话…都是多进程的

AMS,WMS,PMS

如果这些服务不是多进程的,那么每一个app 都集成这些系统服务,将会导致 app 变得很大

2.Binder 有什么优势? 与传统的IPC机制 对比

2.1 传统的IPC机制 – Linux

传统的通信机制:管道, 共享内存, socket,消息队列

ProcessA ,B通信
	1. ProcessA 通过 系统调用 copy_from_user ,将信息 copy进 内核空间

	2. ProcessB 通过 系统调用 copy_to_user, 将信息 copy 进 ProcessB的用户空间

	3. 通信完成, 两次copy

2.2 Binder 与 传统IPC的对比图

在这里插入图片描述

性能:Binder只需要copy一次  -- mmap

特点:基于C/S 架构,易用性搞

安全性:为每个APP分配UID(身份识别),为每一个进程打上UID的标签  支持实名和 匿名

实名就是 系统服务 eg:AMS 获取 通过 getSystemService("activity"), 通过名字来获取服务,这种是需要注册到SM中的

匿名就是 自己创建的服务

2.3 进程空间划分

内存的划分图:

在这里插入图片描述

2.2.1 进程分 用户空间 + 内核空间,两个进程的用户空间是进程隔离的,而同一进程的用户空间和内核空间也是隔离的(通过API调用)

2.2.2 两个进程的内核空间是真实指向 同一块物理空间的

2.2.3 所有进程 的 内核空间,都是映射在同一块物理空间的,虚拟空间 和 物理空间 是通过坐标一一对应的 

2.2.4 我们所说的 用户空间 和 内核空间  都是 虚拟空间

3.Binder是如何做到一次copy的? mmap

ProcessA ,B通信
	1. ProcessA 通过 系统调用 copy_from_user ,将 信息 copy进 内核空间

	2. 然后,系统将 信息 存入 内核空间

	3. ProcessB 的 部分用户空间 和 部分内核空间 指向同一块 物理空间  (跟传统IPC不同的地方,传统IPC不会对 虚拟空间映射做处理)

	4. 在ProcessB需要取信息的时候,直接到 物理空间中取出来,直接用就好了,不用再次copy

4.MMAP的原理讲解?

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

这个过程是由驱动来完成的   java层 mmap方法 --》 驱动层 binder_mmap

e.g. 
    1.用户是不能直接操作,文件的,因为用户在app里是虚拟空间,而文件在硬盘上,是物理空间。
    2.使用mmap 可以将 虚拟空间的 一部分内存空间 映射到 真实的屋里空间上去
    3.从而达到 用户在虚拟空间中写入数据,就相当于在 真正在操作 磁盘上的文件

4.1 源码 如何做到映射

在这里插入图片描述

5.Binder机制是如何跨进程的?

在这里插入图片描述

扫描二维码关注公众号,回复: 12486720 查看本文章
通过一次copy

6.描述AIDL生成的Java类细节?

1. (远程服务)服务端定义好接口,客户端发起方法调用 e.g. addPerson

2. 客户端会自动生成 Proxy.java类,服务端Stub会实现 addPerson方法

3. 首先会生成 两个包 (客户端用来发送数据的包 data 和用来接收服务端数据的包reply)

4. 其次 客户端 会通过 mRemote.transact(int, data, reply, flag),与服务端通信  (此时 客户端的线程会挂起, 一般都是同步通信)

5. 然后就到了服务端的Stub中的onTransact (code, data, reply, flags)方法, 通过code 区分不同的方法

6. 最后调用到 服务端实现的 具体方法,如果有 返回值的,写入到reply包中

6.1 服务端如何 知道 调用的哪个方法?

如果接口中有多个方法,客户端通过 transact(int, 第一个参数,来指定调用的方法名,而不会使用string的字符串,节省空间

7.四大组件 底层的通信机制

通过binderService为例讲解,过程中干了什么,最终连接成功能返回一个IBinder

7.1 客户端如何 获取 服务端的IBinder对象

在这里插入图片描述

  1. 客户端与SM进行通信(SM是固定的Handler – 就是0,好找),通过实名获取到AMS的 IBinder
    2.通过 AMS的IBinder 与 AMS 进行通信, 请求BindService
    3.那么AMS就会执行 scheduleBindService 到 远程服务的onBind方法,拿到远程服务的IBinder对象

7.2 服务端如何将IBinder对象返回

在这里插入图片描述

  1. 同客户端一样的,远程服务端 需要获取到AMS的 IBinder对象
  2. 通过AMS的IBinder对象与AMS进行通信,发布自己的(远程服务的)IBinder对象给AMS
  3. 通过 AMS的 IBinder对象将远程服务的 ibinder对象 返回给客户端 (c.conn.connected(r.name.service)-- 就会调用 服务的onServiceConnected方法)

7.3 总流程

在这里插入图片描述

7.4 bindService 整个过程 有几次跨进程?

客户端与 ServiceManager 也属于 跨进程

总共 跨了 6次 进程,只是为了拿到IBinder对象,拿到之后,客户端与服务端通信只需要通过这个IBinder对象来进行就可

7.4 AMS和 Binder在同一个进程嘛?

不在,AMS在系统层,而Binder在驱动层

8.为什么Intent不能传递大数据?

https://wanandroid.com/wenda/show/13775
每日一问 | Activity与Fragment的那些事,“用起来没问题,我都要走了,你崩溃了?”

mmap分配的内存:(1M - 8K) 这还不包括 数据头

8.1 如果传递 超过这个大小的数据,肯定是会崩溃的

8.2 部分同学传递 520 k 就崩溃了,为什么?

如果 传递数据 是同步的,那么 mmap size是 1M - 8K

如果 传递数据 是异步的,那么 mmap size是 (1M - 8K)/2

8.2 部分同学传递 300 k 就崩溃了,为什么?

可能是已经使用过部分空间,然后申请的空间 > 剩余mmap的大小

参考资料

  1. 在腾讯课堂中,享学提供的源码分析课程

猜你喜欢

转载自blog.csdn.net/HeartCircle/article/details/108747432