ServiceManager作为Native层Service的管理员,有着极其重要的作用,主要表现两个方面:
1、对于服务端来说,系统所有的服务提供者都需要向ServiceManager注册。
2、对于客户端来说,所有客户端如果想要获得某个系统服务的代理,必须向ServiceManager申请相应的服务端代理。
1、打开Binder设备文件;
2、告诉Binder驱动程序自己是Binder上下文管理者;
3、进入一个死循环,充当Service的角色,等待Client的请求。
从上面可以看出,打开Binder的过程的过程分为两步:
1、打开Binder设备;
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 = binder_open(128*1024);
//成为Service manager
if (binder_become_context_manager(bs)) {
LOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
//在binder_loop中循环检测binder中是否有新的请求
binder_loop(bs, svcmgr_handler);
return 0;
}
main函数主要有三个功能:
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;
}
上面打开Binder设备的过程其实就是构建一个binder_state结构体对象,然后对其各个成员初始化的过程。我们来看一下binder_state数据结构:
struct binder_state {
//文件描述符,这里指的是/dev/binder设备文件描述符
int fd;
//把设备文件/dev/binder映射到进程空间的起始地址,这里就是128*1024
void *mapped;
//映射的空间大小
unsigned mapsize;
};
这个结构体只有三个成员变量,其中fd是底层binder设备的文件描述符,mapped是ServiceManager得到的虚拟空间地址,这块虚拟空间映射了底层binder的物理地址,而mapsize是这块虚拟空间的大小,也就是128*1024。
从上面可以看出,打开Binder的过程的过程分为两步:
1、打开Binder设备;
2、用Binder的物理地址映射为ServiceManager可用的虚拟地址;