ServiceManager作为Native层Service的管理员,有着极其重要的作用,主要表现两个方面:
1、对于服务端来说,系统所有的服务提供者都需要向ServiceManager注册。
2、对于客户端来说,所有客户端如果想要获得某个系统服务的代理,必须向ServiceManager申请相应的服务端代理。
main函数主要有三个功能:
1、打开Binder设备文件;
2、告诉Binder驱动程序自己是Binder上下文管理者;
3、进入一个死循环,充当Service的角色,等待Client的请求。
上面打开Binder设备的过程其实就是构建一个binder_state结构体对象,然后对其各个成员初始化的过程。我们来看一下binder_state数据结构:
这个结构体只有三个成员变量,其中fd是底层binder设备的文件描述符,mapped是ServiceManager得到的虚拟空间地址,这块虚拟空间映射了底层binder的物理地址,而mapsize是这块虚拟空间的大小,也就是128*1024。
从上面可以看出,打开Binder的过程的过程分为两步:
1、打开Binder设备;
同时我们注意到, ServiceManager本身也是一个Service,他需要先向Binder注册自己,而且要把自己注册为“管理员”,那么这个注册过程是怎样的呢?我们来看源码:
这一步的入口是binder_loop():
上面的过程表明了Service_manager进入循环的过程,主要分为三个步骤:
1、先通过发送BC_ENTER_LOOPER消息告诉底层,ServiceManager将要进入循环了;
2、在死循环中读取客户端的请求;
3、处理请求;
上面的第一步是通过向Binder发送BC_ENTER_LOOPER消息实现的,第二步通过BINDER_WRITE_READ可以读取Binder中的数据(请求);第三步需要调用binder_parse去处理客户端的请求,我们主要看一下这个过程。
这个函数中我们只关心BR_TRANSACTION分支,通过调用func去解析拿到的请求,然后把返回值作为回应通过binder_send_reply()函数返回给客户端。
因此func()就是svcmgr_handler():
从svcmgr_handler的case分支我们可以看出,作为Service_manager主要完成三个功能:
1、得到一个Service;
2、添加一个Service;
3、列出所有的Service;
下面我们分别看一下这三个功能的实现方式,我们先从add一个Service开始:
从add的过程可以看出,
所谓向ServiceManager注册一个服务,其实就是为当前的Service创建svcinfo的结构体,并把该结构体添加到svclist中。
那么我们可以推测,find的过程无非就是去svclist中查找svcinfo的过程:
这个过程确实如我们所料,需要通过find_svc()在svclist中寻找需要的Service并把该Service节点发送给请求的Client。
那么list Service的请求只需要把svclist返回给Client即可:
经过这些过程,ServiceManager就完成了解析数据的过程,下面就需要把相应的数据返回给客户端。
在binder_parse()中又调用binder_send_reply()函数完成回应的操作:
在给Binder发送返回值时,构建了data的数据,并把reply放入其中,并标记了数据的大小,最后通过binder_write()函数将数据写到Binder中,而且写的方法仍然是调用ioctl()。
1、对于服务端来说,系统所有的服务提供者都需要向ServiceManager注册。
2、对于客户端来说,所有客户端如果想要获得某个系统服务的代理,必须向ServiceManager申请相应的服务端代理。
下面从源码分析ServiceManager的启动流程和服务流程。
- @Service_manager.c(frameworks/base/cmds/servicemanager)
- int main(int argc, char **argv) {
- struct binder_state *bs;
- void *svcmgr = BINDER_SERVICE_MANAGER;
- //打开binder设备
- bs = <span style="color:#ff0000;">binder_open</span>(128*1024);
- //成为Service manager
- if (<span style="color:#ff0000;">binder_become_context_manager</span>(bs)) {
- LOGE("cannot become context manager (%s)\n", strerror(errno));
- return -1;
- }
- svcmgr_handle = svcmgr;
- //在binder_loop中循环检测binder中是否有新的请求
- <span style="color:#ff0000;">binder_loop</span>(bs, svcmgr_handler);
- return 0;
- }
1、打开Binder设备文件;
2、告诉Binder驱动程序自己是Binder上下文管理者;
3、进入一个死循环,充当Service的角色,等待Client的请求。
下面我们就分别介绍这三个步骤。
一、打开Binder设备
- @binder.c(\frameworks\base\cmds\servicemanager\)
- struct binder_state *binder_open(unsigned mapsize) {
- //创建binder_state结构体并分配内存
- struct binder_state *bs;
- bs = malloc(sizeof(*bs));
- //打开binder设备
- bs->fd = open("/dev/binder", O_RDWR);
- bs->mapsize = mapsize;
- //将binder物理空间映射为ServiceManager可用的虚拟空间
- bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
- //将结构体返回给servicemanager
- return bs;
- }
- struct binder_state {
- //文件描述符,这里指的是/dev/binder设备文件描述符
- int fd;
- //把设备文件/dev/binder映射到进程空间的起始地址,这里就是128*1024
- void *mapped;
- //映射的空间大小
- unsigned mapsize;
- };
从上面可以看出,打开Binder的过程的过程分为两步:
1、打开Binder设备;
2、用Binder的物理地址映射为ServiceManager可用的虚拟地址;
二、ServiceManager成为服务管理员的过程
在Android中,每个注册的Service,Binder都会给他分配一个唯一的int型的句柄,Client可以用该句柄向ServiceManager请求相应的Service,而负责这个管理任务的正是ServiceManager。也就是说, Service需要先向ServiceManager注册自己,并得到自己的服务句柄,然后Client需要拿这个int型的句柄向ServiceManager请求相应的Service,ServiceManager再把相应的Service代理对象发送给Client使用。同时我们注意到, ServiceManager本身也是一个Service,他需要先向Binder注册自己,而且要把自己注册为“管理员”,那么这个注册过程是怎样的呢?我们来看源码:
- int binder_become_context_manager(struct binder_state *bs)
- {
- //向Binder驱动发送BINDER_SET_CONTEXT_MGR的消息
- return ioctl(bs->fd, <span style="color:#ff0000;">BINDER_SET_CONTEXT_MGR</span>, 0);
- }
我们看到,当ServiceManager向Binder驱动发送BINDER_SET_CONTEXT_MGR的消息时,Binder就会把他注册为“管理员”。
三、Service_manager服务过程
3.1、Service_manager的执行流程
经过前面两步的操作,我们不仅打开了Binder,而且把当前的ServiceManager注册成为了管理员, 下面要做的就是去承担管理员的职责,也就是接收各种请求。这一步的入口是binder_loop():
- 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,ServiceManager将要进入LOOPER状态了
- binder_write(bs, readbuf, sizeof(unsigned));
- for (;;) {
- //准备要发送的数据
- bwr.read_size = sizeof(readbuf);
- bwr.read_consumed = 0;
- bwr.read_buffer = (unsigned) readbuf;
- //与底层Binder通讯,得到客户端的请求
- res = <span style="color:#ff0000;">ioctl</span>(bs->fd, BINDER_WRITE_READ, &bwr);
- //用func解析请求并构建应答返回给客户端
- res = <span style="color:#ff0000;">binder_parse</span>(bs, 0, readbuf, bwr.read_consumed, <span style="color:#ff0000;">func</span>);
- }
- }
1、先通过发送BC_ENTER_LOOPER消息告诉底层,ServiceManager将要进入循环了;
2、在死循环中读取客户端的请求;
3、处理请求;
上面的第一步是通过向Binder发送BC_ENTER_LOOPER消息实现的,第二步通过BINDER_WRITE_READ可以读取Binder中的数据(请求);第三步需要调用binder_parse去处理客户端的请求,我们主要看一下这个过程。
3.2、ServiceManager处理请求并回应客户端的过程
ServiceManager是通过binder_parse()的函数来处理请求的:- int binder_parse(struct binder_state *bs,struct binder_io *bio,uint32_t *ptr,uint32_t size,binder_handler func){
- while (ptr < end) {
- uint32_t cmd = *ptr++;
- switch(cmd) {
- case BR_NOOP:
- case BR_TRANSACTION_COMPLETE:
- case BR_INCREFS:
- case BR_ACQUIRE:
- case BR_RELEASE:
- case BR_DECREFS:
- break;
- <span style="color:#ff0000;">case BR_TRANSACTION</span>: {
- struct binder_txn *txn = (void *) ptr;
- binder_dump_txn(txn);
- if (func) {
- unsigned rdata[256/4];
- struct binder_io msg;
- struct binder_io reply;
- bio_init(&reply, rdata, sizeof(rdata), 4);
- bio_init_from_txn(&msg, txn);
- //调用service_manager.c中的svcmgr_handler去处理数据
- res = func(bs, txn, &msg, &reply);
- //将Service_manager对客户端的回应数据(reply)返回给Binder驱动
- binder_send_reply(bs, &reply, txn->data, res);
- }
- ptr += sizeof(*txn) / sizeof(uint32_t);
- break;
- }
- case BR_REPLY:
- case BR_DEAD_BINDER:
- case BR_FAILED_REPLY:
- case BR_DEAD_REPLY:
- default:
- }
- }
- return r;
- }
3.2.1、处理请求过程
我们先来看一下请求的处理过程,也就是func()的流程,这里的func来自于调用binder_loop()时的参数:- binder_loop(bs, svcmgr_handler);
- int svcmgr_handler(struct binder_state *bs,struct binder_txn *txn,struct binder_io *msg,struct binder_io *reply){
- switch(txn->code) {
- case SVC_MGR_GET_SERVICE:
- case SVC_MGR_CHECK_SERVICE:
- //得到一个Service
- s = bio_get_string16(msg, &len);
- ptr = do_find_service(bs, s, len, txn->sender_euid);
- bio_put_ref(reply, ptr);
- return 0;
- case SVC_MGR_ADD_SERVICE:
- //添加一个Service
- s = bio_get_string16(msg, &len);
- ptr = bio_get_ref(msg);
- allow_isolated = bio_get_uint32(msg) ? 1 : 0;
- if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated))
- return -1;
- break;
- case SVC_MGR_LIST_SERVICES: {
- //得到当前所有的Service
- 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;
- }
- }
- return 0;
- }
1、得到一个Service;
2、添加一个Service;
3、列出所有的Service;
下面我们分别看一下这三个功能的实现方式,我们先从add一个Service开始:
- int do_add_service(struct binder_state *bs,uint16_t *s,unsigned len,void *ptr,unsigned uid,int allow_isolated) {
- struct svcinfo *si;
- //检查当前注册的Service的uid和注册的服务名称是否有权限
- if (!svc_can_register(uid, s)) {
- return -1;
- }
- //查看是否已经add过了
- si = find_svc(s, len);
- if (si) {
- if (si->ptr) {
- svcinfo_death(bs, si);
- }
- si->ptr = ptr;
- } else {
- si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
- si->ptr = ptr;
- si->len = len;
- memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
- si->name[len] = '\0';
- si->death.func = svcinfo_death;
- si->death.ptr = si;
- si->allow_isolated = allow_isolated;
- si->next = svclist;
- //把当前需要注册的Service添加到svclist中,完成注册过程
- svclist = si;
- }
- }
那么我们可以推测,find的过程无非就是去svclist中查找svcinfo的过程:
- void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len, unsigned uid) {
- struct svcinfo *si;
- //从svclist链表中得到当前请求的Service信息
- si = find_svc(s, len);
- if (si && si->ptr) {
- //得到一个Service需要这个Service的许可
- if (!si->allow_isolated) {
- //还要检查申请者的uid是否匹配
- unsigned appid = uid % AID_USER;
- if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
- return 0;
- }
- }
- return si->ptr;
- } else {
- return 0;
- }
- }
那么list Service的请求只需要把svclist返回给Client即可:
- case SVC_MGR_LIST_SERVICES: {
- unsigned n = bio_get_uint32(msg);
- si = svclist;
- while ((n-- > 0) && si)
- si = si->next;
- if (si) {
- //把svclist返回给请求者
- bio_put_string16(reply, si->name);
- return 0;
- }
- return -1;
- }
3.2.2、回应客户端的过程
在3.2.1中的三个请求处理过程中,特别是get和list Service的请求,最终都需要给客户端相应回应的,我们看到在这两个请求的处理最后,都将相应的回应数据放入了reply的指针中,当从svcmgr_handler()返回后,就把数据带到了binder_parse()中,我们再来回顾一下这里的代码:- int binder_parse(struct binder_state *bs,struct binder_io *bio,uint32_t *ptr,uint32_t size,binder_handler func){
- while (ptr < end) {
- switch(cmd) {
- case BR_TRANSACTION: {
- struct binder_txn *txn = (void *) ptr;
- binder_dump_txn(txn);
- if (func) {
- //reply就是svcmgr_handler()中得到的回应
- res = func(bs, txn, &msg, &reply);
- //将回应数据(reply)返回给Binder驱动
- binder_send_reply(bs, &reply, txn->data, res);
- }
- ptr += sizeof(*txn) / sizeof(uint32_t);
- break;
- }
- }
- }
- return r;
- }
- void binder_send_reply(struct binder_state *bs, struct binder_io *reply, void *buffer_to_free, int status) {
- struct {
- uint32_t cmd_free;
- void *buffer;
- uint32_t cmd_reply;
- struct binder_txn txn;
- } __attribute__((packed)) data;
- data.cmd_free = BC_FREE_BUFFER;
- data.buffer = buffer_to_free;
- data.cmd_reply = BC_REPLY;
- data.txn.target = 0;
- data.txn.cookie = 0;
- data.txn.code = 0;
- if (status) {
- data.txn.flags = TF_STATUS_CODE;
- data.txn.data_size = sizeof(int);
- data.txn.offs_size = 0;
- data.txn.data = &status;
- data.txn.offs = 0;
- } else {
- data.txn.flags = 0;
- data.txn.data_size = reply->data - reply->data0;
- data.txn.offs_size = ((char*) reply->offs) - ((char*) reply->offs0);
- data.txn.data = reply->data0;
- data.txn.offs = reply->offs0;
- }
- //向Binder写回应的数据
- binder_write(bs, &data, sizeof(data));
- }
- int binder_write(struct binder_state *bs, void *data, unsigned len) {
- struct binder_write_read bwr;
- int res;
- bwr.write_size = len;
- bwr.write_consumed = 0;
- bwr.write_buffer = (unsigned) data;
- bwr.read_size = 0;
- bwr.read_consumed = 0;
- bwr.read_buffer = 0;
- //向Binder写数据
- res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
- if (res < 0) {
- fprintf(stderr,"binder_write: ioctl failed (%s)\n", strerror(errno));
- }
- return res;
- }
经过以上步骤,就完成了一次完整的请求调用过程。
四、总结
我们用两张图来总结ServiceManager提供服务的过程。4.1、ServiceManager初始化流程