温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

3. Android binder设计篇

发布时间:2020-07-17 17:01:25 来源:网络 阅读:1047 作者:rongwei84n 栏目:移动开发


一. 引言--女娲造人的故事

在天地混沌之际,上神女娲因为觉得自己太孤单,没人跟它一起嗨,决定按照自己的模样添加一些生物;于是呢,捏泥为人,并赋予了人生育的能力,所以女娲被称为了人类的母亲;

神话故事很美好,解释了人类的来源,但是这个逻辑中其实有个缺陷,就是女娲从哪里来的?

那有些同学就会问了,这里说Binder设计,为什么要提到女娲造人的故事呢?这是因为二者在源头这个问题的处理上有异曲同工之妙,嗯,后面会再做说明。


二. Android Binder简介

Andoid Binder从Open Binder发展而来,提供了跨进程通信机制;其实linux已经提供很多的跨进程机制,比如管道,共享内存等等,那为什么google要使用binder呢?

其实,大家也可以思考下,针对于移动设备这种低配置的设备(相对于服务器),新的进程间通信机制需要具备什么新的优点呢?

1. 内存节省,因为移动设备的低配置,所以需要新的通信机制尽可能的节省资源,binder在跨进程数据拷贝时只进行一次;

2. 高效性,比如对于手机这种东西,大家肯定希望它反应迅速,界面流畅;

3. 安全性,手机涉及了大量的用户隐私,比如支付宝账号,电话本联系人号码,短信记录,通话记录等等;

在linux系统中对于权限安全性管理,UID是一个很重要的东西,所以对于安全性,binder就在binder driver里面负责填写调用进程的UID和PID;相比一些在应用程序填写UID和PID的进程间通信机制,安全性得到了极大提高。


总体来说,Binder肯定是一个不错的进程间通信机制,否则android经过这么多年的发展,如果Binder不是足够优秀的话,以google的技术实力,早就被google替换了吧!


三.Binder通信关系总图

Binder作为Android里面进程间通信机制,主要有4个模块参与这个过程,分别是

client

service

ServiceManager

Binder Driver


client和service作为通信的模块很容易理解,因为client需要和service通信,所以它们两个必然会成为通信的一部分。


那service manager和Binder driver起的作用是什么呢?


service manager提供service的注册,查询等服务,那说的再明白一点,就是service Binder本地对象把自己和一个名字添加到service manager注册;

这样,client就可以向service manager通过指定的名字去查询之前注册的service,从而找到对应的Binder实体对象,再继而生成属于自己进程的Binder 引用对象。

最后把这个属于自己进程的Binder引用对象和自己进程内的一个Binder代理对象对应起来;这样client就间接的拥有了service Binder本地对象的引用,进而可以和service通信。


那Binder driver是做什么用的呢?

Binder driver提供的是桥梁的作用,比如从service注册是service manager,抑或从client到service mangager查询service,以及从client到service的通信,都需要通过Binder driver。

所以Binder driver提供了一个桥梁,同时在通信的过程中记录了一些数据。


为了更好的说明,先上一张整体Binder的关系图。

3. Android binder设计篇


这张图已经基本包括了binder通信过程中的所有对象,我们可以用言语来简略的描述下这个过程和各个对象的含义,至于更详细的我们后面再讲。


过程简短描述:


1. 首先这张图有两个空间,用户空间和内核空间;client, service,service manager运行在用户空间;而binder driver运行在内核空间。


2. service manager首先注册为binder driver的服务管理者,注册的过程中,service manager会调用open和mmap方法来通知binder driver为它分配一块最大不超过4MB的内存,当然这个大小可以由service manager来指定,service manager指定的是128KB。这块内存同时被两个虚拟地址应用,一个binder driver的一个是service manager的。

换句话就是说binder driver为service manager分配了一块同时被内核空间和用户空间映射的内存。

这也是binder驱动的精华,通过这种虚拟内存双重映射,减少了binder driver和service manager之间的数据拷贝。


3. 这样,binder driver就记录下了与service manager 对应的binder实体对象(也就是图中的sm binder实体)。

并且强制规定sm binder实体对象对应的是句柄值是0。也就是其他进程来访问service,只要它传到binder driver的句柄值是0,那就意味着目标service就是service manager。

然后service manager进程进入等待状态,等待别的进程来唤醒。比如别的进程要注册service或者查询service。


4. service进程启动后,同样会通过open和mmap方法通知binder driver为service进程分配一块不超过4MB的内存,一般应用程序的是1MB左右(1mb - 8kb)。

同第2点一样,这块内存也被binder driver内核空间和service进程用户空间的虚拟地址同时映射。

然后向service manager注册service;正如第2点所言,binder driver强制规定了0号句柄对应的是service manager实体对象,所以service进程只要传入0号句柄,然后把想注册的service一起传入过来就可以了。


5. binder driver接到service的ioctl调用后,找到第2点描述的sm binder实体,然后通过这个sm binder实体找到service manager对应的进程。

此时,service manager的进程正在睡眠等待状态,于是binder driver把要处理的工作封装成一个binder_transaction丢给service manager进程,也就是把数据拷贝到binder driver为service manager分配的那块内存(也就是第2步binder driver为service manager分配的那块内存),这也是binder数据传输的唯一一次数据拷贝,然后唤醒它。


6. 此时,service进程会返回service进程用户空间,然后会再次进入binder driver,并且进入等待状态;它需要等待service manager注册service的返回结果。


7. service manager进程被唤醒后,回到service manager用户空间,同时把binder driver拷贝过来的数据读取出来,把名称和从binder driver传入的句柄值保存起来,再次执行结果通过ioctl指令通知binder driver。

8. service manager进程回到binder driver之后,通过之前第5步产生的binder_transaction找到之前调用的binder driver的service进程和线程,把第7点从service manager返回的结果读出来,然后拷贝到binder driver为service分配的内存,再唤醒service线程。


9. service manager在binder driver完成之后,会再次进程等待状态。


10. service进程被service manager进程唤醒之后,会回到service进程的用户空间,然后把第8步binder driver拷贝service进程内存的数据读取出来(这块内存在binder driver中,被service进程和binder driver同时映射),再完成最后的逻辑。


11. client进程启动后,也会像service和service manager一样通过open和mmap方法请求binder driver为client进程分配一块内存用户进程间通信。


12. client进程向service manager发起查询service请求,同时传入要查询service的名称,传入的binder句柄值是0,也就是对应着service manager。


13. binder driver接受到client的查询请求后,根据句柄值0找到service manager的binder实体对象(sm binder实体),然后通过sm binder实体对象找到service manager进程。此时,service manager进程正处于等待状态。


14. binder driver把从client传入的数据拷贝到为service manager分配的那块内存,生成一个binder_transaction,然后唤醒service manager进程。


15. client进程经过一些处理后进入等待状态,等待service manager来唤醒。


16. service manager被唤醒后,把binder driver拷贝给它的数据读取出来,当然最重要的是从client进程传入的service 名称。通过查找,找到名称对应的句柄值。也就是第7点那个名称和句柄值。然后通过ioctl再次回到binder driver。


17. binder driver通过binder_transaction找到第15点的client进程和线程,通过从service manager返回的句柄值找到binder driver里面对应的service 实体对象。然后唤醒client线程。


18. 在binder driver里面,client线程根据service 实体对象,生成属于client进程的binder引用对象,也就是一个句柄值,再返回client进程用户空间。


19. 在client进程用户空间,把句柄值拷贝出来,封装成一个BpBinder对象,BpBinder对象里面mHandle值就保存了这个句柄值。


20. client和service通信,client使用第19步获取到的mHandle句柄值,发送给binder driver。


21. binder driver根据mHandle句柄值找到client进程内对应的binder引用对象,再根据binder引用对象找到它对应的binder实体对象,再根据binder实体对象找到其所在的binder进程。然后把数据拷贝到binder driver为service进程分配的那块内存,再唤醒service进程。


22. client进程的调用线程进入等待状态。


23. 由于binder实体对象有个cookie值指向用户空间service进程的的service地址,所以service在被唤醒后,它可以找到是由哪个service组件来响应此次服务(service进程内可能不止一个service组件)。


24. service完成自己的逻辑后,再次通过binder_ioctl通知binder driver,告诉binder driver处理结果,然后再唤醒client进程。这个过程就和service manager通知service是一样的了。

这样,整个通信过程就基本结束了。



ps:

1. 这里说的service和android应用里面说的4大组件service并不是一个概念,这里的service指的是提供Binder服务的Binder本地对象。


2. 上面说的Binder代理对象,Binder引用对象,Binder实体对象,Binder本地对象是按照从client到service的顺序的,可以按个解释下这几个对象的含义。

a. Binder代理对象,运行在client用户空间,对应的类是BpBinder,实现的关键在于它有个句柄mHandle变量,通过这个变量可以在Binder driver内核空间里面找到对应的Binder引用对象。

b. Binder引用对象,运行在Binder driver内核空间,对应的数据是binder_ref结构体。

c. Binder实体对象,运行在Binder driver内核空间,对应的数据是binder_node结构体。

d. Binder本地对象,运行在service用户空间,对应的数据是BBinder,其实就是一个提供服务的Binder service。


3. 可能大家看到看到对于service manager在binder driver中, client和并没有binder引用对象,而其他service在client进程中却有binder 引用对象,这是为什么呢?

这个问题就回到文章开始的第一点,里面在描述女娲造人关于源头这个问题上的时候,我们说神话故事里面假设女娲是事先存在的,从而弥补了这个故事里面的漏洞。

那在binder机制里面,也有这个问题:就是client通过service manager拿到service的binder句柄值,那么service怎么拿到service manager的句柄值呢?

就好比说人是女娲造的,那女娲又是哪里来的呢?

好吧,跟神话故事一样,我们也是假设service manager是事先存在的,并且规定它的句柄值就是0。

那么client和service只要传入句柄0就可以找到service manager在binder driver中的binder实体对象,自然也不需要binder 引用对象了。

而且service manager进程也不会像其他service进程一样,可能存在多个service服务。


4. service manager请求binder driver为它分配的内存是128kb,一般应用程序(client, service)请求binder driver为它分配的内存是1MB - 8KB。

这是我们要求使用binder时不能传输大于1MB数据的原因,比如通过intent传输图片,很有可能会超过binder传输上限。当然这个我们在后面分析代码的时候会看到。

详见:

android_proj/framework/base/libs/binder/ProcessState.cpp

#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))


5. 在上图中大家看到有些service进程中可能存在多个service组件,比如service2进程。它们都通过binder driver注册到了service manager,但是它们有不同的名称对应以及不同的service组件地址,这两个区别分别会被service manager和binder driver(通过binder_node结构体的cookie数据)所记住。

所以可以区分。


6. binder线程池,用户空间的程序有个线程池来响应binder driver,但是有个上限,一般是15个线程,详见

android_proj/framework/base/libs/binder/ProcessState.cpp

open_driver(){

   ...

   size_t maxThreads = 15;  

   result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);

   ...

}

但是需要说明的是这15个线程指的是binder driver请求用户空间程序创建的最大线程数(当应用程序线程数不足以响应binder请求时,binder driver会请求应用程序分配线程),并不包括用户空间程序主动注册到binder driver的。



四. binder机制中的数据结构

在初步了解binder机制的通信过程后,我们需要更深一步的了解binder通信,所以需要简单讲解下binder通信过程中的数据结构。


用户空间数据binder driver内核空间数据描述
flat_binder_objectbinder_node

binder service对象描述,每个添加到binder driver的service都会对应一个binder_node,包括service manager也是

flat_binder_object顾名思义就是压扁了的binder_object,为什么要压扁呢?是为了传输的需求,所以把binder对象从用户空间传输到binder driver内核空间的时候,就需要用到这个数据结构,比如addService的时候。

client,service进程
binder_proc

对应一个进程,当进程调用open方法打开binder driver的时候,binder driver会保存这个进程的相关信息,就是用binder_proc这个数据结构。

在上面我们说起过,一个进程中可能有多个service组件,比如service2进程,那在binder driver里面也是这种关系。

binder_proc和binder_node是一对多的关系。

binder_proc使用了红黑树的数据结构来描述了它里面binder_node。

红黑树的数据结构大家有不清楚可以百度下。

线程binder_threadbinder_thread是线程在binder driver中的描述,所以binder_proc和binder_thread的对应关系也是1对多,也是用红黑树来组织的。
binder_transaction_databinder_transaction

binder_transaction用来描述binder driver里面的一个事务。事务在数据库里面用的比较多,binder driver也借用了这个概念。

那binder_transaction_data就刚好是用来描述从用户空间到内核空间传输binder_transaction数据的。


-binder_buffer

在前面描述过,binder driver会为每个进程分配一个不超过4MB的内存,用来传输数据。

那怎么来管理这块内存呢?

binder driver把这块内存划成一页一页来管理,那一个binder_buffer就表示一页。

-binder_ref

binder driver里面的binder引用对象。

binder_ref主要的作用就是拥有一个句柄值,同时指向一个binder_node binder实体对象。

句柄值对应client里面的binder代理对象BpBinder里面的mHandle,所以client可以根据mHandle找到内核对应的binder_ref数据。

binder_ref关联的binder_node对象,这样,找到binder_ref后,就可以进一步找到binder_node。

binder_node上面讲过,关联了binder_proc,以及service进程里面的service组件,也就是binder本地对象。

所以,通过这一层层的关联,都连接起来了。

-binder_ref_death

跟binder本地对象死亡通知有关。

我们知道binder机制是这样的引用的。

BpBinder(mHandle)->binder_ref->binder_node->BBinder binder本地对象。

那如果binder本地对象意外的挂了呢?比如service所在进程由于程序逻辑错误异常退出了,调用它的client怎么办呢?

所以为了部分解决这个问题,binder因为死亡通知这个功能,当binder本地对象消亡之后,需要通知正在监听它的binder_ref client。

-binder_workbinder driver的工作项描述,后面再具体描述。
binder_write_readbinder_write_read

ioctl指令BINDER_WRITE_READ的数据结构。






五. 实名binder对象和匿名binder对象

所谓的实名和匿名是针对service manager而言的,就是service manager知不知道这个binder对象的存在,并且给它一个名字相对应。

正如第一步里面所描述的女娲造人的故事,女娲可以造人,但是人也可以造人。如果把女娲比喻成service manager,那么第一代人就是实名binder对象,第一代人以及后面的人造的人就是匿名binder对象;

因为它对于女娲这个service manager而言,女娲并不知道它们的存在和名字。

这个比喻如果难以理解的话,那再举个更加现实的栗子:

如果一个人想进入火车候车室,那么他需要火车票或者站台票,那我们现在来做如下比喻:


例子binder
进入候车室实现binder通信功能
火车票实名binder对象
站台票匿名binder对象
铁道部
service manager

检票口binder driver


1. 假如把进入候车室这个功能比喻成实现binder通信这个功能,那么:


2. 火车票和站台票都可以进入候车室,也就是说实名binder和匿名binder都可以完成进程间通信功能,这点并没有什么区别。


3. 由于火车票是实名制的,所以铁道部能知道卖出的票和购买人的***一一对应;但是对于站台票,铁道部并不能知道这种对应关系;

那对于service manager和实名binder,匿名binder也是这种关系 -- service mangager清楚的知道所有实名binder的名称,binder服务所在的进程等等信息,但是对于匿名binder却一无所知,它甚至不知道匿名binder的存在。


4. 购买站台票不是想买就可以买的,需要持有火车票吃可以购买站台票;

那对于实名binder和匿名binder也是如此,匿名binder不是想创建就能创建的,首先需要得到一个实名binder,通过实名binder得到匿名binder,具体例子可以参考bindService得到一个匿名binder的实现。


5. 对于检票口,不管是火车票还是站台票都会从检票口通过,所以检票口可以记录一些信息;同样,对于binder driver,不管是实名binder还是匿名binder都会通过binder driver,binder driver也会记录它们的信息。


六. binder ioctl指令


ioctl指令名称含义注释
BINDER_WRITE_READ最重要的ioctl指令,后面可以执行很多binder命令操作。独特的先写后读的设计,给予了用户空间程序更多的便利。
BINDER_SET_IDLE_TIMEOUT暂未使用
BINDER_SET_MAX_THREADS设置binder driver可以请求用户空间进程最大线程数。不包括用户空间进程主动注册到binder driver的线程。
BINDER_SET_IDLE_PRIORITY暂未使用
BINDER_SET_CONTEXT_MGR通知binder driver,当前进程成为binder机制上下文,也就是service mangagerbinder driver里面只能存在一个service manager,多次调用会出错。
BINDER_THREAD_EXIT通知binder driver线程退出
BINDER_VERSION返回当前binder driver版本号


七. binder命令

binder命令按照命令的流向性分为两大类:

1. BC_XXX

2. BR_XXX

从用户空间流向binder driver的命令被称为BC_XXX,也就是binder command的简称;相应的从binder driver流向用户空间进程的称为BR_XXX,也就是binder return的简称。如下图:

3. Android binder设计篇


对于所有的binder 命令,可以用下面两张表来描述:

具体可以参考./working_directory/kernel/goldfish/driver/staging/android/binder.h

enum BinderDriverCommandProtocol {

  ...

}


enum BinderDriverReturnProtocol {

  ...

}


3. BC_XXX

命令名称含义注释
BC_TRANSACTION意思是进行一次transaction,比如addService,getService,或者client跨进程调用service方法等等。最重要的binder命令之一,一般通过ioctl--BINDER_WRITE_READ来和binder driver交互。
BC_REPLY回复binder driver比如addService的时候,service manager在处理完自己的逻辑后会发送此命令到binder driver,告诉binder driver自己处理结果。
BC_ACQUIRE_RESULT暂不支持
BC_FREE_BUFFER

通知binder driver去释放一个binder_buff的内存,参数int表示此binder_buff在用户空间进程的虚拟映射地址。

一般是在处理完一个事务之后,通知binder driver释放先关内存。
BC_INCREFS

通知binder driver增加目标service 弱引用, 参数int表示目标service的handle值,


BC_ACQUIRE

通知binder driver增加目标service 强引用,参数int表示目标service的handle值.


BC_RELEASE

通知binder driver减少目标service强引用,参数int表示目标service的handle值.


BC_DECREFS

通知binder driver减少目标service弱引用,参数int表示目标service的handle值.


BC_INCREFS_DONE

通知binder driver BR_INCREFS命令执行完毕,一般由service进程在处理完binder driver的BR_INCREFS命令后向binder driver发出。


BC_ACQUIRE_DONE通知binder driver BR_ACQUIRE命令执行完毕,一般由service进程在处理完binder driver的BR_ACQUIRE命令后向binder driver发出。

因为binder driver在请求service进程增加一个service组件的强引用之后,它需要等待service组件增加强引用计数的结果,它需要根据这个结果修改自己的一些状态。

BC_ATTEMPT_ACQUIRE暂不支持
BC_REGISTER_LOOPER

通知binder driver此进程进入BINDER_LOOPER_STATE_REGISTERED状态,再经过一些处理就会进入就绪状态,可以处理进程的事务。

此命令是binder driver通知用户空间进程创建线程后,用户空间进程创建线程后会调用此命令,通知binder driver此线程已经准备好。


BC_ENTER_LOOPER用户空间进程主动请求binder driver通知此线程可以处理进程间binder 通信请求,一般如果没有事情做的话,会进入等待状态。

此命令和BC_REGISTER_LOOPER的区别就是

BC_ENTER_LOOPER是用户空间进程主动通知binder driver的,

BC_REGISTER_LOOPER是binder driver发现此用户空间进程的线程池无法响应binder通信,需要创建新线程;然后向目标用户空间进程发出请求创建线程命令

用户空间进程创建线程完毕后,会调用BC_REGISTER_LOOPER通知binder driver。

BC_EXIT_LOOPER

通知binder driver此线程退出


BC_REQUEST_DEATH_NOTIFICATION

client请求binder driver注册目标service组件的死亡通知


以便在目标serive组件死亡的时候得到通知,然后client可以处理自己的逻辑。
BC_CLEAR_DEATH_NOTIFICATION

client通知binder driver取消注册对某个service binder本地对象的死亡通知监听


BC_DEAD_BINDER_DONE

client通知binder driver对某个service进程的binder本地对象死亡通知处理完毕。




4. BR_XXX

命令名称含义注释
BR_ERROR

通知用户空间进程,binder driver处理出现异常


BR_OK

通知用户空间进程,binder driver处理成功


BR_TRANSACTIONbinder driver请求用户空间进程处理一个事务,事务的数据方法binder_transaction_data结构体中,

比如addService的时候,binder driver请求service manager去注册一个service。

BR_REPLY
binder driver通知用户空间进程处理完毕比如用户空间进程发起的BC_TRANSACTION 处理完毕后,binder driver就会反馈BR_REPLY
BR_ACQUIRE_RESULT暂不支持
BR_DEAD_REPLY

binder driver反馈目标binder对象已经死亡,返回错误。


BR_TRANSACTION_COMPLETEbinder driver反馈事务处理完成
BR_INCREFS

binder driver请求用户空间进程增加指定binder本地对象的弱引用


BR_ACQUIRE

binder driver请求用户空间进程增加指定binder本地对象的强引用


BR_RELEASE

binder driver请求用户空间进程减少指定binder本地对象的强引用


BR_DECREFS

binder driver请求用户空间进程减少指定binder本地对象的弱引用


BR_ATTEMPT_ACQUIRE

暂不支持


BR_NOOP

没有什么操作


BR_SPAWN_LOOPER

binder driver请求用户空间进程分配一个线程;这种情况一般是在用户空间进程线程池无法处理binder driver间通信请求的情况下。


BR_FINISHED暂不支持
BR_DEAD_BINDER

通知用户空间进程所监听的binder本地对象已经销毁


BR_CLEAR_DEATH_NOTIFICATION_DONE

在用户空间进程请求BC_CLEAR_DEATH_NOTIFICATION命令后,binder driver返回这个命令通知用户空间进程


BR_FAILED_REPLYbinder driver返回失败









八. 引用计数

在第七点的表中,我们提到了所有的Binder协议命令,其中包括类似BC_INCREFS,BC_ACQUIRE,BC_RELEASE,BC_DECREFS之类的命令,表中解释是维护binder对象的引用计数;那为什么要进行这样的设计呢?


那我们可以来做这样一种假设:

client进程引用service进程的一个binder本地对象正在通信,如果这个时候service进程把这个binder本地对象回收了怎么办?


为了解决这个问题,binder机制使用了引用的概念:


在Java里面,我们知道维护一个对象的生命周期可以通过强引用,软引用,弱引用和虚引用来实现(具体的区别大家可以百度,里面一些区别和技巧还是很有用的,特别是软引用用来实现图片的缓存),只要一个对象被从垃圾回收的根节点强引用所关联,那么它是不会被回收的。


所以,类似的,binder机制里面也采用这个概念。


那,binder driver为什么不直接引用binder 本地对象呢?


这是因为binder driver是在内核空间,binder本地对象在service进程的用户空间,不能直接引用。


所以,binder 机制才通过这种通过命令调用的方式,通知service进程为指定的binder本地对象增加/减少引用,从而达到维护用户空间service进程binder本地对象生命周期的目的。



九. 死亡通知机制

通过上面几点介绍,一到七点保证了binder间进程通信,第八点保证了生命周期管理,一切看起来都那么完美。

但是,还是有意外情况发生,那就是:


提供服务的service进程死亡了怎么办?


对应这个问题,client和binder driver都爱莫能助,因为它们也无法控制service进程的生命周期。又回到了第八点阐述的那个问题:

client进程引用service进程的一个binder本地对象正在通信,如果service进程的binder本地对象不存在了怎么办?


对于service进程死亡,一般可以分为两种情况:

1. 正常死亡,比如程序自己退出

2. 异常退出,比如因为程序里面的一个逻辑错误导致进程退出

如果是第1种情形,程序会自己主动close掉自己进程打开的binder driver;从而调用到binder driver的binder_release函数。

如果是第2种情形,操作系统会帮我们close,从而也可以调用binder driver的binder_release函数。


所以,上面两种可能都可以在binder driver的binder_release函数中去解决。


binder 机制死亡通知的过程是这样的:

a. client进程拿到指向service进程binder本地对象的引用后,它可以向这个service进程binder本地对象请求注册一个死亡通知(其实就是BpBinder,因为它实现了死亡通知的接口)。

b. binder driver记录下了这层对应关系。

c. 当binder driver检测到目标service进程已经死亡时,它找到这个进程所有binder本地对象在binder driver里面对应的binder实体对象。

d. 然后根据binder实体对象找到所有引用它的binder引用对象,如果发现binder引用对象有注册死亡通知,那么就封装一个binder_work项给binder引用对象所在的进程,然后唤醒它;让那个进程去完成自己的逻辑。


至此,binder设计篇内容全部提供完毕,下面会写一些binder实现篇的东西,也就是从代码的角度来分析这些内容。



向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI