汇总binder相关一些常见面试题-安卓系统常见面试题-CSDN博客
binder讨论的一些场景面试题
问题1:binder中有多个进程作为客户端通过servicemanager获取service的bpbinder,bpbinder都会有一个handle,那么多个进程获取同一个service对应的handle一样么?
是的,多个进程获取同一个服务对应的
BpBinder
的 handle 是一样的。在 Android 的 Binder IPC 机制中,
ServiceManager
负责管理系统中的各种服务。当一个客户端进程请求某个服务时,它会通过ServiceManager
获取到服务的Binder
引用(即BpBinder
),这个引用在内部包含了一个 handle,该 handle 是一个整数值,唯一标识了这个服务在 Binder 驱动中的位置。由于不同进程获取的都是同一个服务的引用,所以它们获取到的
BpBinder
中的 handle 是相同的。这个 handle 用于在 Binder 驱动层进行通信时标识目标服务,从而确保客户端进程能够正确地与目标服务进行交互。总结来说:
- 不同进程通过
ServiceManager
获取同一个服务的BpBinder
。- 这些
BpBinder
对象中的 handle 是一样的,因为它们都指向同一个服务。- 这个 handle 是用于在底层 Binder 驱动中唯一标识该服务的。
希望这个回答能帮到你!如果你有更多问题,请随时提问。
问题2:请问binder通讯过程中是否可以传递bpbinder对象?
是的,在 Binder 通信过程中可以传递
BpBinder
对象。
BpBinder
是一个客户端侧的 Binder 引用,它在跨进程通信中可以被当作普通的 Binder 对象传递。具体过程如下:
创建
BpBinder
: 客户端进程通过ServiceManager
获取服务的BpBinder
引用。传递
BpBinder
: 在进行 Binder 通信时,这个BpBinder
可以作为参数附带在Parcel
中传递给其他进程。使用
BpBinder
: 接收方进程会收到这个BpBinder
引用,并可以通过它与原服务进行通信。这种机制使得 Binder 能够灵活地支持对象引用的传递和跨进程交互,是 Android IPC 的核心特性之一。
问题3:请问同binder 服务端进程自己进程内部如果进行binder调用需要经过binder驱动吗,需要和不需要请详细描述?
这个要看情况和调用方式:
一 通过aidl的方式,AIDL 接口生成的时候,有区分是否是本地进程还是远程进程
Stub 的空构造函数。而Stub 本身又是Binder 的子类。调用了Binder 的attachInterface 方法。
|
|
|
|
分别保存了当前类的实例对象(This)和当前类接口描述符(DESCRIPTOR),其实就是
private static final java.lang.String DESCRIPTOR = “com.example.aidlapplication.IMyAidlInterface”;
当前类的全路径,这也是我们在使用aidl 的时候服务端和客户端必须要保证相同路径下的原因,因为他被保存下来作为参数用于比对当前类是否是本地类还是远程。
所以在
|
|
|
|
参考这篇:android Binder queryLocalInterface 本地与远程-CSDN博客
二 通过bind service
这种方式可能还是要通过binder去调用,但在binder驱动内部,可能还是有一定的优化流程。 #TODO
问题4:Android App进程天生支持binder通讯的原理是什么,刚开始初始化时候自带了几个binder线程?
zygote 启动的时候就支持了binder通讯,所有后面的app孵化之后,也会自带binder通讯。
zygote 在 init的时候:
1. 启动 ProcessState ProcessState::self()
2. 启动线程池:proc->startThreadPool();
|
|
new ProcessState(kDefaultDriver);
|
|
mDriverFD(open_driver(driver)) 打开驱动
mMaxThreads(DEFAULT_MAX_BINDER_THREADS) 最大线程数
mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); 映射内存 BINDER_VM_SIZE 默认 1M- 2PageSize
|
|
|
|
app刚开始启动Binder时候:
1、打开binder驱动
2、binder映射对应的内存
3、启动binder线程
4、获取IPCThread对象
5、通知binder驱动已经进入循环
这部分内容在zygote中已经干完了,所以app在fork出来后,会自带binder功能。
问题5:请描述一下binder通讯起来后,需要新开binder线程的创建是怎么一个过程?
[[#2. 启动线程池:proc->startThreadPool();]]
|
|
|
|
|
|
IPCThreadState::self() 构造之后,启动线程池
|
|
参考:
Binder之ProcessState和IPCThreadState类分析-CSDN博客
问题6:请问binder的如何使用异步请求,优势是什么,但频繁使用相关风险?
在 Android 的 Binder IPC(进程间通信)机制中,异步请求的使用可以提高应用的响应性和用户体验。下面是异步请求的基本使用方法、优势及其频繁使用的风险。
如何使用异步请求
AIDL 接口定义:在定义 AIDL 接口时,可以使用
oneway
修饰符来标记某个方法为异步调用。例如:1
oneway void asyncMethod();
实现异步方法:在服务端实现该方法时,可以将其放入一个新的线程中执行,从而不会阻塞主线程:
1 2 3 4 5 6 7 8
public void asyncMethod() { new Thread(new Runnable() { @Override public void run() { // 执行耗时操作 } }).start(); }
客户端调用:客户端调用该异步方法时,不需要等待结果,调用将立即返回。
回调接口:为了获取结果,通常会在 AIDL 接口中定义一个回调接口,客户端在调用时传入实现了该接口的对象。服务端在处理完成后,通过该回调将结果返回:
1 2 3 4 5
interface Callback { void onResult(ResultType result); } void asyncMethod(Callback callback);
优势
提高响应性:异步请求不会阻塞主线程,用户界面能够保持响应,提供更好的用户体验。
资源利用率:在执行耗时操作时,可以更有效地利用 CPU 资源,不至于造成单一线程的瓶颈。
更好的扩展性:对于需要频繁通信的场景,异步请求可以有效地处理并发请求,提高了系统的处理能力。
风险
复杂性:异步编程增加了代码的复杂性,尤其是在管理状态和错误处理时,可能导致难以追踪的 bug。
线程管理:频繁创建和销毁线程可能导致性能问题或资源消耗过大,应该合理管理线程池的大小。
回调地狱:使用回调接口时,可能会导致“回调地狱”问题,代码的可读性和可维护性下降。
数据一致性:在异步操作中,如果多个线程同时修改同一数据,可能会导致数据不一致的问题,需要适当的同步机制。
内存泄漏:如果持有对 Activity 或 Context 的引用而未能及时清除,可能会导致内存泄漏。使用弱引用或在 Activity 销毁时清除引用是必要的。
总的来说,虽然异步请求在 Android Binder 通信中具有诸多优势,但需要在实现时注意潜在的风险和复杂性。合理设计的异步机制能够提高应用的性能和用户体验。
问题7:跨进程通讯一般都需要通过ServiceManager进行getService获取bpbinder,但普通app经常使用系统组件Service的bindService进行跨进程通讯也可以获取bpbinder,这个是啥原理?
客户端 bindService
|
|
|
|
会直接去通过AMS 调用bindIsolatedService
|
|
|
|
跨进程拿到AMS的binder 去调用bindIsolatedService
|
|
远端服务如果没有启动,前面还有一个oncreate的过程。是在 scheduleCreateService 的时候调用。调用后才会去bind 相关服务
create 过程
|
|
调用 service.onCreate();
|
|