Binder使用client-server的通信方式:
一个进程作为server提供诸如视频/音频解码,视频捕获,地址本查询,网络连接等服务;多个进程作为client向server发送服务请求,获得所需要的服务。
对于Binder而言,Binder可以看成是Server提供的实现某一个特定服务的访问接入点,Client可以通过这个‘地址’向server发送服务请求来是用该服务;对于Client而言,Binder可以看成是通向server的管道入口,要想和某一个server通信首先就要建立这个通道并且获得通道入口。
Binder是一个实体位于Server中的对象,该对象提供一套方法用以实现对服务的请求,就像类的成员函数,
Binder框架定义了四个角色:Server,Client,ServiceManager(以后简称SMgr)以及驱动。其中Server,Client,SMgr运行于用户空间,驱动运行于内核空间。
Binder驱动虽然默默无闻,却是通信的核心。尽管名叫‘驱动’,实际上和硬件设备没有任何关系,只是实现方式和设备驱动程序是一样的:它工作于内核态,提供open(),mmap(),poll(),ioctl()等标准文件操作,以字符驱动设备中的misc设备注册在设备目录/dev下,用户通过/dev/binder访问该它。驱动负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。驱动和应用程序之间定义了一套接口协议,主要功能由ioctl()接口实现,不提供read(),write()接口,因为ioctl()灵活方便,且能够一次调用实现先写后读以满足同步交互,而不必分别调用write()和read()。
,SMgr的作用是将字符形式的Binder名字转化成Client中对该Binder的引用,使得Client能够通过Binder名字获得对Server中Binder实体的引用。
下面从MediaService的例子来分析Binder的使用:
1、ServiceManager,这是AndroidOS 的整个服务的管理程序
2、MediaService,这个程序里面注册了提供媒体播放的服务程序MediaPlayerService.
3、MediaPlayerClient,这个是与MediaPlayerService交互的客户端程序。
首先是MediaService
在frameworks/base/Media/MediaServer/Main_mediaserver.cpp中。
intmain(int argc, char** argv)
{
//获得一个ProcessState实例
sp<ProcessState>proc(ProcessState::self());
//得到一个ServiceManager对象
sp<IServiceManager> sm = defaultServiceManager();
MediaPlayerService::instantiate();//初始化MediaPlayerService服务
ProcessState::self()->startThreadPool();//看名字,启动Process的线程池?
IPCThreadState::self()->joinThreadPool();//将自己加入到刚才的线程池?
}
一步一步看:
1、ProcessState
第一个调用的是ProcessState::self(),然后负赋值给proc变量,程序运行完,proc会自动delete内部的内容,所以就自动释放了先前分配的资源。
在frameworks/base/include/binder/ProcessState.cpp中
sp<ProcessState>ProcessState::self()
{
if(gProcess != NULL) return gProcess;
AutoMutex_l(gProcessMutex);
if(gProcess == NULL) gProcess = new ProcessState;
returngProcess;
}
new的时候会调用ProcessState的构造函数,下面看看构造函数:
ProcessState::ProcessState() : mDriverFD(open_driver()) , mVMStart(MAP_FAILED)
,mManagesContexts(false) , mBinderContextCheckFunc(NULL)
,mBinderContextUserData(NULL) , mThreadPoolStarted(false) ,mThreadPoolSeq(1)
{
if(mDriverFD >= 0) {
//XXX Ideally, there should be a specific define for whether we
//have mmap (or whether we could possibly have the kernel module
//availabla).
#if!defined(HAVE_WIN32_IPC)
//mmap the binder, providing a chunk of virtual address space toreceive transactions.
mVMStart= mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,mDriverFD, 0);
if(mVMStart == MAP_FAILED) {
//*sigh*
LOGE("Using/dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD= -1;
}
#else
mDriverFD= -1;
#endif
}
LOG_ALWAYS_FATAL_IF(mDriverFD< 0, "Binder driver could not be opened. Terminating.");
}
在构造函数的初始化列表中第一个就是open_driver(),返回文件指针,这个文件指针在mVMStart= mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,mDriverFD, 0);的时候使用,我们先看一下open_driver()函数,
staticint open_driver()
{
intfd = open("/dev/binder", O_RDWR);
if(fd >= 0) {
fcntl(fd,F_SETFD, FD_CLOEXEC);
intvers;
status_tresult = ioctl(fd, BINDER_VERSION, &vers);
if(result == -1) {
LOGE("Binderioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd= -1;
}
if(result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
LOGE("Binderdriver protocol does not match user space protocol!");
close(fd);
fd= -1;
}
size_tmaxThreads = 15;
//通过ioctl告诉内核,这个fd所支持的最大线程数是15。
result= ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if(result == -1) {
LOGE("Binderioctl to set max threads failed: %s", strerror(errno));
}
}else {
LOGW("Opening'/dev/binder' failed: %s\n", strerror(errno));
}
returnfd;
}
到这里processState::self()就执行完了,它主要完成的工作有:
1、打开dev/binder设备,这样的话就相当于和内核binder机制有了交互的通道
2、映射fd到内存中,设备fd传进去之后,这块内存和binder设备共享了
2、defaultServiceManager
所在的位置在frameworks/base/lib/binder/IServiceManager.c中
sp<IServiceManager>defaultServiceManager()
{
if(gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex_l(gDefaultServiceManagerLock);
if(gDefaultServiceManager == NULL) {
gDefaultServiceManager= interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
}
}
returngDefaultServiceManager;
}