Binder进程间通信系统第四篇-----Binder进程间通信库

本文拜读参考自罗升杨老师的 《Android系统源代码情景分析》

概述:

Android系统在应用程序框架中将各种Binder驱动程序操作封装成一个Binder库,这样进程就可以方便的调用Binder库提供的接口来实现进程间通信。在Binder库中,Service组件和Client组件分别使用模板类BnInterface和BpInterface来描述,其中,前者成为Binder本地对象,后者称为Binder代理对象。Binder库中的Binder本地对象和Binder代理对象分别对象与Binder驱动程序中的 Binder实体对象和Binder引用对象。以下是两个模板的介绍。

一 模板类BnInterface和BpInterface的定义

模板类BnInterface和BpInterface的定义如下。

frameworks\native\include\binder\IInterface.h

template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
    virtual sp<IInterface>      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<IBinder>& remote);

protected:
    virtual IBinder*            onAsBinder();
};

参数模板 INTERFACE 是一个由进程自定义的 Service 组件接口,模板类 BnInterface 和 BpInterface 都需要实现该接口。在使用 Binder 库开发 Service 组件和 Client 组件时,除了要定义 Service 组件接口之外,还必须要实现一个 Binder 本地对象类和一个 Binder代理对象类,他们分别继承于末模板类 BnInterface 和
BpInterface。

二 模板类 BnInterface

模板类 BnInterface 继承了 BBinder类,后者为 Binder本地对象 提供了抽象的进程间通信接口,定义如下

frameworks\native\include\binder\Binder.h

class BBinder : public IBinder
{
.......

	/*
	* 当一个Binder代理对象通过Binder驱动程序向一个Binder本地对象发出一个进程间通信请求时,Binder驱动程序就会调用
	* 	该Binde本地对象的成员函数 transact  来处请求。
	*
	*/
    virtual status_t    transact(   uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);

......

protected:
    virtual             ~BBinder();

	/*
	* 成员函数 onTransact 是虚函数,它是由 BBinder 的子类,即 Binder本地对象类来实现的,他负责分发与业务相关的进程间通
	* 信请求。事实上,与业务相关的进程间通信请求是由Binder本地对象类的子类,即Service组件来负责处理的。
	*/
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0)	;
.....
};

BBinder类有两个重要的成员函数 transact 和 onTransact。当一个Binder代理对象通过Binder驱动程序向一个Binder本地对象发出一个进程间通信请求时,Binder驱动程序就会调用该Binde本地对象的成员函数 transact 来处请求。成员函数 onTransact 是虚函数,它是由 BBinder 的子类,即 Binder本地对象类来实现的,他负责分发与业务相关的进程间通信请求。事实上,与业务相关的进程间通信请求是由Binder本地对象类的子类,即Service组件来负责处理的。

BBinder 类继承自 IBinder类,IBinder类又继承自 RefBase类。继承了RefBase类的子类的对象均可以通过请指针和弱指针来维护他们的生命周期,也就是说,就是Binder本地对象是通过引用计数技术来维护生命周期的。Binder本地对象受到Binder驱动程序中的Binder实体对象以及运行在Client进程中的Binder代理对象引用。

三 模板类 BpInterface

模板类 BpInterface 继承自 BpRefBase 类,后者为 Binder代理对象 提供了抽象的进程间通信接口,定义如下:

frameworks\native\include\binder\Binder.h

class BpRefBase : public virtual RefBase
{
protected:
                            BpRefBase(const sp<IBinder>& o);
......
    inline  IBinder*        remote()                { return mRemote; }
    inline  IBinder*        remote() const          { return mRemote; }

private:
......
    IBinder* const          mRemote; //它指向一个 BpBinder对象
......
};

}; // namespace android

BpRefBase类有继承自 RefBase类,所以他的子类对象,即 Binde代理对象也可以通过强指针和弱指针来维护维护声明周期。RefBase类中成员变量 mRemote,它指向一个 BpBinder对象,可以通过成员函数 remote来获取。 BpBinder类实现了 BpRefBase类的进程间通信接口,如下:

	class BpBinder : public IBinder
{
public:
                        BpBinder(int32_t handle);

    inline  int32_t     handle() const { return mHandle; }//获取Client组件的句柄值
	
	......
    
    virtual status_t    transact(   uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);

	......

 
private:
    const   int32_t             mHandle;//表示一个Client组件的句柄值

  	......
};

BpBinder 类的成员变量 mHandle 是一个整数,它表示一个Client组件的句柄值,可以通过成员函数 handle() 来获取。成员函数 transact 用来向运行在 Service 进程中的 Service 组件发送进程间通信请求,这是通过 Binder驱动程序间接实现的。BpBinder类的成员函数 transact 会把 BpBinder类的成员变量 mHandle,以及进程间通信数据发送给 Binder驱动程序,这样Binder 驱动程序就能根据这个句柄值来找到对应的 Binder引用对象,继而找到对应的的Binder实体对象,最后就可以将进程间通信数据发送给对应的Service 组件了。

小结:
class BpRefBase : public virtual RefBase // RefBase类的子类对象可以通过强指针和弱指针来维护维护声明周期。
BpRefBase.mRemote ->public BpBinder.transact 向运行在 Service 进程中的 Service 组件发送进程间通信请求
class BpInterface :public BpRefBase

三 IPCThreadState类

无论是 BBinder类,还是 BpBinder 类,他们都是通过 IPCThreadState类来和Binder驱动程序交互的。

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<ProcessState>    mProcess;
......
};

每一个使用了Binder 进程间通信机制的进程都有一个 Binder线程池,用来处理进程间通信请求。对于每一个Binder线程来说,它的内部都有一个 IPCThreadState 对象,我们可以通过 IPCThreadState类的静态成员函数 self() 来获取,并且调用成员函数 transact()来与 Binder 驱动程序交互。在 IPCThreadState 类的静态成员函数 transact 内部,与Binder驱动程序的交互操作又是通过调用成员函数 talkWithDriver() 来实现的,它一方面负责向 Binder 驱动程序发送进程间通信请求,另一方面又负责接收来自 Binder 驱动程序的进程间通信请求。IPCThreadState类的成员变量 mProcess,他指向一个 ProcessState对象,对于每一个使用了 Binder 进程间通信机制的进程来说,它内部都有一个ProcessState对象,他负责初始化Binder设备。即打开设备文件 /dev/binder,以及将设备 /dev/binder 映射到进程的地址空间,由于这个 ProcessState对象在进程范围内是唯一的,所以,Binder线程池中的每一个线程都可以通过它来和Binder驱动建立连接。

class ProcessState : public virtual RefBase{

public:
    static  sp<ProcessState>    self();

......

private:
......
            int                 mDriverFD;
            void*               mVMStart;

......
};

进程中的 ProcessState 对象可以通过 成员函数 self()来获取。调用 self() ,Binder库就会为进程创建一个 ProcessState 对象,并且调用函数 open 来打开设备文件 /dev/binder,接着又调用函数 mmap()将它映射到进程的地址空间,即请求Binder驱动程序为进程分配内核缓冲区。设备文件 /dev/binder 映射到进程的地址空间后,得到的内核缓冲区的用户地址就保存在其成员变量 mVMStart中。

ProcessState 分析

sp<ProcessState> proc(ProcessState::self())

1
//self函数采用单例模式,即每个进程只有一个 ProcessState对象。
sp<ProcessState> ProcessState::self() 
{ 
	Mutex::Autolock _l(gProcessMutex); 
	
	//gProcess是一个全局变量,程序刚开始执行,gProcess一定为空。
	if (gProcess != NULL) { 
	return gProcess; 
	} 
	
	//创建一个 ProcessState 对象,并赋值给 gProcess
	gProcess = new ProcessState("/dev/binder");
	return gProcess; 
}

2 ProcessState的构造
frameworks/native/libs/binder/ProcessState.cpp

static int open_driver()
{
	//dakai Binder设备
	int fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
	if (fd >= 0) {
		int vers = 0;
		//ioctl 查询版本号
		status_t result = ioctl(fd, BINDER_VERSION, &vers);
		if (result == -1) {
			ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
			close(fd);
			fd = -1;
		}
		
		if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
			ALOGE("Binder driver protocol does not match user space protocol!");
			close(fd);
			fd = -1;
		}
		size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
		
		//ioctl 确认最大线程数 :15
		result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
		if (result == -1) {
			ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
		}
	} else {
		ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
	}
	return fd;
}


	//ProcessState的构造函数
ProcessState::ProcessState()
	: mDriverFD(open_driver()) // 打开 Binder 设备
	, mVMStart(MAP_FAILED)//映射内存起始地址
	, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
	, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
	, mExecutingThreadsCount(0)
	, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
	, mStarvationStartTimeMs(0)
	, mManagesContexts(false)
	, mBinderContextCheckFunc(NULL)
	, mBinderContextUserData(NULL)
	, mThreadPoolStarted(false)
	, mThreadPoolSeq(1)
{
	if (mDriverFD >= 0) {

		mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
		if (mVMStart == MAP_FAILED) {
			// *sigh*
			ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
			close(mDriverFD);
			mDriverFD = -1;
		}
	}

	LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}

四 总结

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux老A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值