- 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();
};
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 组件实现原理类图
!