Android(安卓)Binder 机制初步学习 笔记(三)—— Binder 进程通讯库简介
16lz
2021-01-24
- NOTE
- Binder 进程间通讯库
- IInterfaceh
- Binderh
- 1 class BBinder
- 2 class BpRefBase
- BpBinderh
- IPCThreadStateh
- ProcessStateh
- Service 组件实现原理类图
- Client 组件实现原理类图
NOTE
- 源码版本:Android 7.1.2。
- 内核版本:android-goldfish-3.4
- 内核下载:
git clone https://aosp.tuna.tsinghua.edu.cn/kernel/goldfish.git
(清华镜像站) - 以下分析思路均来自老罗的《Android 系统源代码情景分析(修订版)》。
Binder 进程间通讯库
Android
在框架层中将各种Binder
驱动程序封装成了一个通讯库。- 在库中
Binder
的Service
组件与Client
组件分别采用模板类BnInterface
与BpInterface
来描述。 BnInterface
:
Binder
本地对象。- 对应
Binder
驱动中的Binder
实体对象。
BpInterface
:
Binder
代理对象。- 对应
Binder
驱动中的Binder
引用对象。
1. IInterface.h
- 位置:
frameworks/native/include/binder/IInterface.h
class BnInterface
:
template<typename INTERFACE>class BnInterface : public INTERFACE, public BBinder{public: virtual sp queryLocalInterface(const String16& _descriptor); virtual const String16& getInterfaceDescriptor() const;protected: virtual IBinder* onAsBinder();};
class BpInterface
:
template<typename INTERFACE>class BpInterface : public INTERFACE, public BpRefBase{public: BpInterface(const sp& remote);protected: virtual IBinder* onAsBinder();};
- NOTE:
- 模板参数
INTERFACE
是由进程自定义的Service
组件接口,而BnInterface
与BpInterface
都要实现这个接口。 - 除了
Service
组件接口外,还需要实现相应的一个Bn
类和一个Bp
类,它们分别继承于BnInterface
与BpInterface
。
- 模板参数
2. Binder.h
- 位置:
frameworks/native/include/binder/Binder.h
2.1 class BBinder
BnInterface
类继承了BBinder
类。BBinder
为本地对象提供了抽象的进程间通信接口。- 该类有两个重要的成员函数
transact
与onTransact
:
- 当一个
Binder
代理对象通过驱动向一个本地对象发出通信请求时,驱动则会调用该本地对象的成员函数transact
来处理请求。 onTransact
是由Binder
本地对象类实现的,它负责分发与业务相关的进程间通信请求。- 与业务相关的进程间通信请求是由本地对象类的子类,即
Service
组件类来负责处理的。 BBinder
类继承了IBinder
类,而后者继承了RefBase
类。- 由于继承了
RefBase
,则可知Binder
本地对象是通过引用计数技术来维护其生命周期的。 Binder
本地对象收到驱动中的实体对象以及运行在Client
进程中的Binder
代理对象引用,所以它的引用计数技术更加复杂,这一部分以后再慢慢了解。
- 当一个
class BBinder : public IBinder{public: BBinder(); virtual const String16& getInterfaceDescriptor() const; virtual bool isBinderAlive() const; virtual status_t pingBinder(); virtual status_t dump(int fd, const Vector& args); virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); virtual status_t linkToDeath(const sp& recipient, void* cookie = NULL, uint32_t flags = 0); virtual status_t unlinkToDeath( const wp& recipient, void* cookie = NULL, uint32_t flags = 0, wp* outRecipient = NULL); virtual void attachObject( const void* objectID, void* object, void* cleanupCookie, object_cleanup_func func); virtual void* findObject(const void* objectID) const; virtual void detachObject(const void* objectID); virtual BBinder* localBinder();protected: virtual ~BBinder(); virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);private: BBinder(const BBinder& o); BBinder& operator=(const BBinder& o); class Extras; std::atomic mExtras; void* mReserved0;};
2.2 class BpRefBase
BpInterface
类继承了BpRefBase
类。- 类似本地对象,代理对象也采用引用计数技术维护生命周期。
BpRefBase
类中有一个比较重要的成员mRemote
,它指向一个BpBinder
对象,而BpBinder
类则实现了BpRefBase
类的进程间通信接口。
class BpRefBase : public virtual RefBase{protected: BpRefBase(const sp& o); virtual ~BpRefBase(); virtual void onFirstRef(); virtual void onLastStrongRef(const void* id); virtual bool onIncStrongAttempted(uint32_t flags, const void* id); inline IBinder* remote() { return mRemote; } inline IBinder* remote() const { return mRemote; }private: BpRefBase(const BpRefBase& o); BpRefBase& operator=(const BpRefBase& o); IBinder* const mRemote; RefBase::weakref_type* mRefs; std::atomic mState;};
3. BpBinder.h
- 位置:
frameworks/native/include/binder/BpBinder.h
- 成员变量
mHandle
是一个整数,表示一个Client
组件的句柄值,其值可以通过成员函数handle()
获取。 - 成员函数
transact()
:
- 向运行在
Server
进程中的Service
组件发送通信请求,通过Binder
驱动间接实现。 - 将
BpBinder
类的成员mHandle
以及进程间通信数据发送给驱动。 - 驱动根据句柄找到对应
Binder
引用对象,从而找到最终的实体对象,这样才能将数据发送给对应的Service
组件。
- 向运行在
class BpBinder : public IBinder{public: BpBinder(int32_t handle); inline int32_t handle() const { return mHandle; } ...... virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); ......private: const int32_t mHandle; ......};
4. IPCThreadState.h
- 位置:
frameworks/native/include/binder/IPCThreadState.h
- 对于每个
Binder
线程,其内部都有一个IPCThreadState
对象。 - 通过
IPCTreadState
类的self()
函数可以获取相应的对象,并且通过调用它的成员函数transact()
就可以与驱动进行交互。 - 在函数
transact()
内部,它通过成员函数talkWithDriver()
实现与驱动的交互:
- 一方面它负责向驱动发送进程间通信请求。
- 另一方面它也负责接收来自驱动的通信请求。
- 成员变量
mProcess
指向一个ProcessState
对象,它是线程与驱动建立连接的关键。
class IPCThreadState{public: static IPCThreadState* self(); ...... status_t transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); ......private: ...... status_t talkWithDriver(bool doReceive=true); ...... const sp mProcess; ......};
5. ProcessState.h
- 位置:
frameworks/native/include/binder/ProcessState.h
- 对于每个使用了
Binder
机制的进程来说,它的内部都有一个ProcessState
对象:
- 负责初始化
Binder
设备,即打开/dev/binder
。 - 将设备文件映射到进程的地址空间,即请求驱动为进程分配内核缓冲区。
- 负责初始化
ProcessState
对象在进程范围内是唯一的,因此Binder
线程池中线程都可以通过它与Binder
驱动程序建立连接。- 可以通过
self()
函数获取相应的ProcessState
对象:
- 若非第一次调用,则直接返回
ProcessState
对象。 - 若为第一次调用,
Binder
库会为进程创建一个ProcessState
对象,并且调用open()
函数打开设备文件,接着调用mmap()
将设备文件映射到进程地址空间。
- 若非第一次调用,则直接返回
- 映射地址空间后,得到的内核缓冲区用户地址保存在成员变量
mVMStart
中。
class ProcessState : public virtual RefBase{public: static sp self(); ......private: ...... int mDriverFD; void* mVMStart; ......};
6. Service 组件实现原理类图
7. Client 组件实现原理类图
!
更多相关文章
- android 核心组件( 1 ) 常用布局, adapter, handler, UI
- Android开发实践教程
- android 怎样为多媒体文件生成缩略图
- android root权限相关bin程序rageagainsttheca
- Android(安卓)SystemService类注释
- Android源码解析
- Android实现使用流媒体播放远程mp3文件的方法
- Android(安卓)BitTube 学习
- Android(安卓)BroadCast