6.3 服务总管ServiceManager
6.3.1 ServiceManager的原理
前面说过,defaultServiceManager返回的是一个BpServiceManager,通过它可以把命令请求发送给handle值为0的目的端。按照图6-3所示的IServiceManager“家谱”来看,无论如何也应该有一个类从BnServiceManager派生出来并处理这些来自远方的请求吧?
很可惜,源码中竟然没有这样一个类存在!但确实又有这么一个程序完成了BnServiceManager未尽的工作,这个程序就是ServiceManager,它的代码在Service_manager.c中。
注意 通过这件事情是否能感悟到什么?我们确实可以抛开前面所有的那些封装,直接与binder设备打交道。
下面来看ServiceManager是怎么放弃华丽的封装去做Manager的。
1.ServiceManager的入口函数
ServiceManager的入口函数如下所示。
[—>ServiceManager.c]
int main(int argc,char**argv)
{
struct binder_state*bs;
//BINDER_SERVICE_MANAGER的值为NULL,是一个magic number。
void*svcmgr=BINDER_SERVICE_MANAGER;
//①应该是打开binder设备吧?
bs=binder_open(128*1024);
//②成为manager,是不是把自己的handle置为0?
binder_become_context_manager(bs)
svcmgr_handle=svcmgr;
//③处理客户端发过来的请求。
binder_loop(bs,svcmgr_handler);
}
这里,一共有三个重要关键点(即①~③)。必须对其逐一进行分析。
注意 有一些函数是在Binder.c中实现的,此Binder.c不是前面碰到的那个Binder.cpp。
2.打开binder设备
binder_open函数用于打开binder设备,它的实现如下所示:
[—>Binder.c]
/*
这里的binder_open应该与我们之前在ProcessState中看到的一样:
1)打开binder设备
2)内存映射
*/
struct binder_state*binder_open(unsigned mapsize)
{
struct binder_state*bs;
bs=malloc(sizeof(*bs));
……
bs->fd=open("/dev/binder",O_RDWR);
……
bs->mapsize=mapsize;
bs->mapped=mmap(NULL,mapsize,PROT_READ,MAP_PRIVATE,bs->fd,0);
}
果然如此,有了之前所掌握的知识,理解这里真的就不难了。
3.成为老大
怎么才成为系统中独一无二的manager了呢?manager的实现如下面的代码所示:
[—>Binder.c]
int binder_become_context_manager(struct binder_state*bs)
{
//实现太简单了!这个0是否就是设置自己的handle呢?
return ioctl(bs->fd,BINDER_SET_CONTEXT_MGR,0);
}
4.死磕Binder
binder_loop是一个很尽责的函数。为什么这么说呢?因为它老是围绕着binder设备转悠,实现代码如下所示:
[—>Binder.c]
/*
注意binder_handler参数,它是一个函数指针,binder_loop读取请求后将解析
这些请求,最后调用binder_handler完成最终的处理。
*/
void binder_loop(struct binder_state*bs,binder_handler func)
{
int res;
struct binder_write_read bwr;
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);
//接收到请求,交给binder_parse,最终会调用func来处理这些请求。
res=binder_parse(bs,0,readbuf,bwr.read_consumed,func);
}
5.集中处理
往binder_loop中传的那个函数指针是svcmgr_handler,它的代码如下所示:
[—>Service_manager.c]
int svcmgr_handler(struct binder_statebs,struct binder_txntxn,
struct binder_iomsg,struct binder_ioreply)
{
struct svcinfo*si;
uint16_t*s;
unsigned len;
void*ptr;
//svcmgr_handle就是前面说的那个magic number,值为NULL。
//这里要比较target是不是自己。
if(txn->target!=svcmgr_handle)
return-1;
s=bio_get_string16(msg,&len);
if((len!=(sizeof(svcmgr_id)/2))||
memcmp(svcmgr_id,s,sizeof(svcmgr_id))){
return-1;
}
switch(txn->code){
case SVC_MGR_GET_SERVICE://得到某个service的信息,service用字符串表示。
case SVC_MGR_CHECK_SERVICE:
s=bio_get_string16(msg,&len);//s是字符串表示的service名称。
ptr=do_find_service(bs,s,len);
if(!ptr)
break;
bio_put_ref(reply,ptr);
return 0;
case SVC_MGR_ADD_SERVICE://对应addService请求。
s=bio_get_string16(msg,&len);
ptr=bio_get_ref(msg);
if(do_add_service(bs,s,len,ptr,txn->sender_euid))
return-1;
break;
//得到当前系统已经注册的所有service的名字。
case SVC_MGR_LIST_SERVICES:{
unsigned n=bio_get_uint32(msg);
si=svclist;
while((n—>0)&&si)
si=si->next;
if(si){
bio_put_string16(reply,si->name);
return 0;
}
return-1;
}
default:
return-1;
}
bio_put_uint32(reply,0);
return 0;
}