ServiceManager

ServiceManager的启动

ServiceManager进程service_manager.c并没有使用libbinder框架代码,而是自行编写了binder.c直接和Binder驱动来通信,ServiceManager是单线程的进程, 不断地循环在binder_loop()过程来读取和处理事务,从而对外提供查询和注册服务的功能,这样的好处是简单而高效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// service_manager.c
int main(int argc, char **argv) {
struct binder_state *bs;
char *driver;
if (argc > 1) {
driver = argv[1];
} else {
driver = "/dev/binder"; // 默认的Binder设备节点
}

//Step 1: 打开binder驱动,申请128k字节内存
bs = binder_open(driver, 128*1024);
...

//Step 2: 成为上下文管理者
if (binder_become_context_manager(bs)) {
return -1;
}
...

//Step 3: 进入无限循环,处理client端发来的请求
binder_loop(bs, svcmgr_handler);
return 0;
}

启动过程主要划分为以下几个阶段:(每个阶段具体见5.2.1 启动ServiceManager服务)

create_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结构体如下所示。

ServiceManager进程
1
2
3
4
5
6
7
8
9
struct svcinfo
{
struct svcinfo *next;
uint32_t handle; //服务的handle值
struct binder_death death;
int allow_isolated;
size_t len; //服务名的长度
uint16_t name[0]; //服务名
};

整个ServiceManager启动过程的完整流程,这里整个过程都的都离不开Binder驱动层的实现。

ServiceManager启动过程

Other

vndservicemanager

以前,Binder 服务通过 servicemanager 注册,其他进程可从中检索这些服务。在 Android 8 中,servicemanager 现在专供框架使用,而应用进程和供应商进程无法再对其进行访问。

不过,供应商服务现在可以使用 vndservicemanager,这是一个使用 /dev/vndbinder(作为构建基础的源代码与框架 servicemanager 的相同)而非 /dev/binderservicemanager 的新实例。供应商进程无需更改即可与 vndservicemanager 通信;当供应商进程打开 /dev/vndbinder 时,服务查询会自动转至 vndservicemanager

vndservicemanager 二进制文件包含在 Android 的默认设备 Makefile 中。

Author

white crow

Posted on

2023-12-20

Updated on

2024-03-25

Licensed under