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;

}