ServiceManager
ServiceManager的启动
ServiceManager进程service_manager.c并没有使用libbinder框架代码,而是自行编写了binder.c直接和Binder驱动来通信,ServiceManager是单线程的进程, 不断地循环在binder_loop()过程来读取和处理事务,从而对外提供查询和注册服务的功能,这样的好处是简单而高效。
1 | // service_manager.c |
启动过程主要划分为以下几个阶段:(每个阶段具体见5.2.1 启动ServiceManager服务)
首先,打开设备驱动:调用binder_open()方法来打开binder驱动,默认地采用/dev/binder设备节点,申请地内存空间大小为128KB;
其次,注册成为大管家:调用binder_become_context_manager()方法,将自己注册成为binder服务的唯一管家;
通过ioctl系统调用向Binder驱动发送命令BINDER_SET_CONTEXT_MGR,成为上下文的管理者,由于servicemanager进程启动非常早(先于Zygote),可以确定在Binder整体机制正式投入产线之前,就能完成向Binder驱动注册成为大管家的工作。 关于驱动层处理BINDER_SET_CONTEXT_MGR命令的主要任务:
- 保证每个Binder上下文有且仅有一个binder管家实体,如果已存在则不再创建
- 创建binder管家实体,初始化异步事务和binder工作两个队列,并分别增加其强弱引用计数
- 初始化当前binder_context的管家实体(binder_context_mgr_node)和管家uid(binder_context_mgr_uid)信息
- handle等于0的服务实体都是指servicemanager管家实体
最后,等待客户请求:调用binder_loop()方法进入无限循环,作为守护进程,随时待命等待处理client端发来的请求。
servicemanager先向Binder驱动发送BC_ENTER_LOOPER协议,让ServiceManager进入循环。然后再向驱动发送BINDER_WRITE_READ命令, 进入内核态,等待客户端的请求数据。若没有数据,则进入等待状态,直到收到数据后返回用户态,解析并处理,周而复始地不断循环该过程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 // servicemanager/binder.c
void binder_loop(struct binder_state *bs, binder_handler func) {
int res;
struct binder_write_read bwr;
uint32_t readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER;
//向binder驱动发送BC_ENTER_LOOPER协议
binder_write(bs, readbuf, sizeof(uint32_t));
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
//等待客户的数据
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
//解析binder信息
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
}
}
ServiceManager提供的服务
ServiceManager对外提供查询/注册功能,通过接收到客户端进程发送过来的BR_TRANSACTION协议。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 // service_manager.c
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
...
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
...
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len); //服务名
//根据名称查找相应服务
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len); //服务名
handle = bio_get_ref(msg); //服务实体在servicemanager中的handle
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
//注册指定服务
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
uint32_t n = bio_get_uint32(msg);
if (!svc_can_list(txn->sender_pid)) {
return -1;
}
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
}
bio_put_uint32(reply, 0);
return 0;
}
该方法的功能:查询服务,注册服务,以及列举所有服务。不同的code对应不同的工作,定义在IBinder.h文件,跟IServiceManager.h中定义的code具有一一对应关系,具体关系如下所示。
code | IBinder.h | IServiceManager.h |
---|---|---|
1 | SVC_MGR_GET_SERVICE | GET_SERVICE_TRANSACTION |
2 | SVC_MGR_CHECK_SERVICE | CHECK_SERVICE_TRANSACTION |
3 | SVC_MGR_ADD_SERVICE | ADD_SERVICE_TRANSACTION |
4 | SVC_MGR_LIST_SERVICES | LIST_SERVICES_TRANSACTION |
ServiceManager
servicemanager进程里面有一个链表svclist,记录着所有注册的服务svcinfo,每一个服务用svcinfo结构体来表示,该handle值是在注册服务的过程中,由服务所在进程那一端所确定的。svcinfo结构体如下所示。
1 | struct svcinfo |
整个ServiceManager启动过程的完整流程,这里整个过程都的都离不开Binder驱动层的实现。
Other
vndservicemanager
以前,Binder 服务通过 servicemanager
注册,其他进程可从中检索这些服务。在 Android 8 中,servicemanager
现在专供框架使用,而应用进程和供应商进程无法再对其进行访问。
不过,供应商服务现在可以使用 vndservicemanager
,这是一个使用 /dev/vndbinder
(作为构建基础的源代码与框架 servicemanager
的相同)而非 /dev/binder
的 servicemanager
的新实例。供应商进程无需更改即可与 vndservicemanager
通信;当供应商进程打开 /dev/vndbinder
时,服务查询会自动转至 vndservicemanager
。
vndservicemanager
二进制文件包含在 Android 的默认设备 Makefile 中。