好久没有写android相关的技术博客了,由于近期工作中需要做安卓项目,所以唤起了对安卓的重新学习激情。个人认为Binder是安卓的通信灵魂,所以准备从Binder开始研究安卓。
Binder机制中的4个组件Client, Server, Service Manager和Binder驱动关系图如下:
这个图还是比较清楚的能够看出4者之间的调用关系,相信有点安卓经验的朋友应该比较清晰,这里只做个感情的认识,不做进一步的讲解。不过还是要补充2点:
1.Binder驱动和Service Manager在安卓平台中已经实现,开发定制者只需要在用户空间实现自己的Client和Server。
2.Service Manager是个守护进程,用来管理Server,并向Client提供查询Server接口的能力。
下面从framework的角度去详细分析Binder的通信原理.
一. Service Manager是如何成为一个守护进程的?(即Service Manager是如何告知Binder驱动它是Binder机制的上下文管理者)
Service Manager的入口位于service_manager.c文件中的main函数:
- int main(int argc, char **argv)
- {
- struct binder_state *bs;
- void *svcmgr = BINDER_SERVICE_MANAGER;
-
- bs = binder_open(128*1024);
-
- if (binder_become_context_manager(bs)) {
- LOGE("cannot become context manager (%s)\n", strerror(errno));
- return -1;
- }
-
- svcmgr_handle = svcmgr;
- binder_loop(bs, svcmgr_handler);
- return 0;
- }
该函数有3个功能:1.打开Binder设备文件;2.告诉Binder驱动自己是守护进程;3.进入无限循环,充当Server角色,等待Client的请求。
我们直接看第二个功能:
- int binder_become_context_manager(struct binder_state *bs)
- {
- return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
- }
这里通过ioctl来通知Binder驱动自己是守护进程
第三个功能进入循环,等待Client的请求:
- void binder_loop(struct binder_state *bs, binder_handler func)
- {
- int res;
- struct binder_write_read bwr;
- unsigned readbuf[32];
-
- bwr.write_size = 0;
- bwr.write_consumed = 0;
- bwr.write_buffer = 0;
-
- readbuf[0] = BC_ENTER_LOOPER;
- binder_write(bs, readbuf, sizeof(unsigned));
-
- for (;;) {
- bwr.read_size = sizeof(readbuf);
- bwr.read_consumed = 0;
- bwr.read_buffer = (unsigned) readbuf;
-
- res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
-
- if (res < 0) {
- LOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
- break;
- }
-
- res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
- if (res == 0) {
- LOGE("binder_loop: unexpected reply?!\n");
- break;
- }
- if (res < 0) {
- LOGE("binder_loop: io error %d %s\n", res, strerror(errno));
- break;
- }
- }
- }
最后总结一下,Service Manager成为Binder守护进程的过程是这样的:
1.打开/dev/binder文件:open("/dev/binder", O_RDWR);
2.建立128K内存映射:mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
3.通知Binder驱动它是守护进程:binder_become_context_manager(bs);
4.进入循环等待:binder_loop(bs, svcmgr_handler);
在整个过程中,Binder驱动建立了一个struct binder_proc结构,一个struct binder_thread结构,一个struct binder_node结构,这样Service_Manager就在Binder中担负起守护进程的职责了。
二.Server和Client是如何获得Service Manager接口的?(即defaultServiceManager接口是如何实现的)
Servvice Manager在Binder机制中既充当守护进程的角色也充当着Server的角色,但它与一般的Server不一样。对于一般的Server来说,Client想要获得Server的远程接口,必须通过Service Manager提供的getService来获得,这本身就是一个使用Binder机制来进行通信的过程。而对于Service Manager这个Server来说,Client想要获得Service Manager接口,却不必通过Binder机制来获得,因为Service Manager接口是个特殊的引用,它的引用句柄一定是0。
在Binder机制中,Server和Client拿到这个Service Manager接口之后怎么用呢?
对Server来说就是调用IServiceManager::addService这个接口来和Binder驱动交互;对于Client来说是调用IServiceManager::getService接口来和Binder驱动交互。
三.Server是如何把自己的服务启动起来的?Server Manager是如何为Server提供服务的?(即IServiceManager::addService接口是如何实现的)
这里通过一个例子老说明Binder机制中Server的启动过程。众所周知在安卓系统中提供了多媒体播放的功能 ,这个功能是以服务的形式提供的,下面通过分析MediaPlayerService的实现来了解Media Server的启动过程。
- int main(int argc, char** argv)
- {
- sp<ProcessState> proc(ProcessState::self());
- sp<IServiceManager> sm = defaultServiceManager();
- LOGI("ServiceManager: %p", sm.get());
- AudioFlinger::instantiate();
- MediaPlayerService::instantiate();
- CameraService::instantiate();
- AudioPolicyService::instantiate();
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
- }
Server启动起来后,就会在一个循环中等待Client的请求。
四.Service Manager是如何为Client提供服务的?(即IServiceManager::getService接口是如何实现的)
假设Service Manager和MediaPlayerService已经启动完毕,Service Manager现在等待Client的请求。
这里举例说的Client便是MediaPlayer了,MediaPlayer继承于IMediaDeathNotifier类,里面有一个静态成员函数getMediaPlayerService,它通过IServiceManager::getService接口来获得MediaPlayerService的远程接口。
-
- const sp<IMediaPlayerService>&
- IMediaDeathNotifier::getMediaPlayerService()
- {
- LOGV("getMediaPlayerService");
- Mutex::Autolock _l(sServiceLock);
- if (sMediaPlayerService.get() == 0) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder;
- do {
- binder = sm->getService(String16("media.player"));
- if (binder != 0) {
- break;
- }
- LOGW("Media player service not published, waiting...");
- usleep(500000);
- } while(true);
-
- if (sDeathNotifier == NULL) {
- sDeathNotifier = new DeathNotifier();
- }
- binder->linkToDeath(sDeathNotifier);
- sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
- }
- LOGE_IF(sMediaPlayerService == 0, "no media player service!?");
- return sMediaPlayerService;
- }