android启动过程分析——Context Manager

Context Manager概要

  • context manager 对应的进程为servicemanager,它先于Service Server与服务客户端运行,首先进入接收IPC数据的待机状态,处理来自Service Server或服务客户端的请求。
  • 每当Service Server注册服务时,Context Manager都会把服务的名称与Binder节点编号注册到自身的服务目录中,该服务目录通过根文件系统下的/system/service程序即可查看。
  • service程序以IPC应答数据的形式接收Context Manager服务目录中的服务名称,并将接收到的服务名称输出到画面中。

Context Manager 的运行

  • context manager 与其他android服务不一样,它采用C语言编写,以便使其与Binder Driver紧密衔接。Context Manager的源码在/frameworks/native/cmds/servicemanager/的service_manager.c文件中。

  • Context Manager 的main()函数大致可以分为以下三部分,分别为binder_open()函数(用来打开Binder Driver并创建IPC数据接收Buffer)、binder_become_context_manager()函数(注册特殊节点,即0号Binder节点),以及binder_loop()函数(用来不断接收IPC数据)。

    int main()
    {

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
struct binder_state *bs;
// 调用binder_open()函数,将引起open()与mmap()函数调用,调用open()函数打开Binder Driver,而调用mmmap()函数则生成IPC数据的Buffer。Context Manager使用大小128KB的Buffer来接收IPC数据。
bs = binder_open(128*1024);
if (!bs) {
ALOGE("failed to open binder driver\n");
return -1;
}
// 与Service Server和服务客户端不同,这是Context Manager特有的语句,用于访问Binder Driver,并将自身的Binder节点设置为0号节点。在binder_become_context_manager()函数中仅有一条ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0)语句,当向Binder Driver传递BINDER_SET_CONTEXT_MGR的ioctl命令后,Binder Driver将通过在binder_ioctl()函数中调用binder_new_node()函数,生成编号为0的Binder节点,并将其注册到binder_context_mgr_node全局变量中
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
selinux_enabled = is_selinux_enabled();
sehandle = selinux_android_service_context_handle();
selinux_status_open(true);
if (selinux_enabled > 0) {
if (sehandle == NULL) {
ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
abort();
}
if (getcon(&service_manager_context) != 0) {
ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
abort();
}
}
union selinux_callback cb;
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
cb.func_log = selinux_log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
// Context Manager 在binder_loop()函数中使用for语句不断等待接收IPC数据(通过Binder Driver),当接收到IPC数据时,binder_parse()函数就会被调用用来分析IPC数据
binder_loop(bs, svcmgr_handler);
return 0;

}

  • Context Manager 的主要任务包括服务注册与服务检索两大任务,具体由svcmgr_handler()函数根据RPC代码执行。

    int svcmgr_handler(struct binder_state bs,struct binder_transaction_data txn,struct binder_io msg,struct binder_io reply)

{

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
if (txn->target.ptr != BINDER_SERVICE_MANAGER)
return -1;
if (txn->code == PING_TRANSACTION)
return 0;
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s\n", str8(s, len));
return -1;
}
if (sehandle && selinux_status_updated() > 0) {
struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
if (tmp_sehandle) {
selabel_close(sehandle);
sehandle = tmp_sehandle;
}
}
switch(txn->code) {
// 服务客户端在检索服务时执行该部分代码。服务客户端首先通过RPC数据传递服务名称,从do_find_service()函数自身的服务列表中获取带有指定名称的服务编号,而后bio_put_ref()函数生成binder_object结构体,该结构体被包含到IPC应答数据的RPC数据中,最终IPC应答数据传递给Binder Driver。
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
if (!handle)
break;
bio_put_ref(reply, handle);
return 0;
// 当Service Server注册服务时执行该部分代码。Context Manager调用do_add_service()函数将IPC数据的RPC数据包含的服务名称与Binder节点编号注册到自身的服务目录中。而后将IPC应答数据传递给Binder Driver。
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = bio_get_ref(msg);
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, txn->sender_euid)) {
ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
txn->sender_euid);
return -1;
}
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
default:
ALOGE("unknown code %d\n", txn->code);
return -1;
}
bio_put_uint32(reply, 0);
return 0;

}

总结

Context Manager是Binder Driver的重要组成部分之一。android平台启动的时候,在init进程中会初始化Context Manager,其是android本地服务和Java服务的管理者,提供服务注册、服务检索、服务响应等作用。