共计 9032 个字符,预计需要花费 23 分钟才能阅读完成。
Service Manager 是整个 Binder 机制的守护进程,用来管理开发者创建的各种 Server,并且向 Client 提供查询 Server 远程接口的功能。Service Manager 在 init.rc 中作为 service 启动,运行在一个独立的进程中。而 Client 和 Server 也运行在独立的进程中。这样,如果 Client 和 Server 需要和 Service Manager 进行通信,就需要使用进程中通信。事实告诉我们,它们之间的通信同样使用了 Binder 机制。因此,Service Manager 在充当 Binder 机制的守护进程的角色的同时,也在充当 Server 的角色。它是一种特殊的 Server,下面分析一下它的代码,从 main 函数开始。
1.---> service_manager.c
2.
3.int main(int argc, char **argv)
4.{
5. struct binder_state *bs;
6. void *svcmgr = BINDER_SERVICE_MANAGER;
7.
8. bs = binder_open(128*1024);
9.
10. if (binder_become_context_manager(bs)) {11. ALOGE("cannot become context manager (%s)\n", strerror(errno));
12. return -1;
13. }
14.
15. svcmgr_handle = svcmgr;
16. binder_loop(bs, svcmgr_handler);
17. return 0;
18.}
main 函数比较简单,主要完成三个功能
- 打开 Binder 设备。
- 告诉 Binder 驱动程序自己是 Binder 上下文管理者。
- 进入一个无穷循环,充当 Server 的角色,等待 Client 的请求。
Binder 设备打开调用了 binder_open 函数,具体代码如下。
1.---> binder.c
2.
3.struct binder_state
4.{
5. int fd;
6. void *mapped;
7. unsigned mapsize;
8.};
9.
10.struct binder_state *binder_open(unsigned mapsize)
11.{
12. struct binder_state *bs;
13.
14. bs = malloc(sizeof(*bs));
15. if (!bs) {
16. errno = ENOMEM;
17. return 0;
18. }
19.
20. // 打开 Binder 设备文件
21. bs->fd = open("/dev/binder", O_RDWR);
22. if (bs->fd < 0) {23. fprintf(stderr,"binder: cannot open device (%s)\n",
24. strerror(errno));
25. goto fail_open;
26. }
27.
28. bs->mapsize = mapsize;
29. // 对设备文件进行内存映射
30. bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
31. if (bs->mapped == MAP_FAILED) {32. fprintf(stderr,"binder: cannot map device (%s)\n",
33. strerror(errno));
34. goto fail_map;
35. }
36.
37. /* TODO: check version */
38.
39. // 返回 binder_state
40. return bs;
41.
42.fail_map:
43. close(bs->fd);
44.fail_open:
45. free(bs);
46. return 0;
47.}
binder_open 函数打开 Binder 的设备描述符“/dev/binder”,之后对 binder 设备进行内存映射。映射后的内存就是用来 Binder 数据传输的 buffer。函数执行成功后返回用来维护 Binder 状态的结构体 binder_state。
完成 Binder 设备的初始化后,程序调用 binder_become_context_manager 函数使 Service Manager 变成 Binder 管家,管家具有固定的 Binder handle(0)。代码很简单,仅仅调用 ioctl 让 Binder 设备去执行 BINDER_SET_CONTEXT_MGR 命令。具体实现在 Binder driver 中完成。
1.---> binder.c
2.
3.int binder_become_context_manager(struct binder_state *bs)
4.{5. return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
6.}
之后 Service Manager 调用 binder_loop 函数进入到循环状态,并提供了一个回调函数,等待用户的请求。Service Manager 的客户端既包括应用程序(查询和获取服务),也包括 Server(注册服务)。客户端和服务器通信前,必须先获得服务器代理,需要通过 Service Manager 来查询服务得到。但现在我们需要得到的是 Service Manager 的服务,该如何实现呢?这是因为 Service Manager 是 Binder 管家,它有固定的 Binder handle,就是 0。任何的客户端都通过 handle 0 来创建 Service Manager 的代理对象。接下来看 binder_loop 的实现。
1.---> binder.c
2.
3.void binder_loop(struct binder_state *bs, binder_handler func)
4.{
5. int res;
6. struct binder_write_read bwr;
7. unsigned readbuf[32];
8.
9. bwr.write_size = 0;
10. bwr.write_consumed = 0;
11. bwr.write_buffer = 0;
12.
13. // 使用 BC_ENTER_LOOPER 告诉 Binder 驱动,Binder 管家进入循环
14. readbuf[0] = BC_ENTER_LOOPER;
15. binder_write(bs, readbuf, sizeof(unsigned));
16.
17. for (;;) {18. bwr.read_size = sizeof(readbuf);
19. bwr.read_consumed = 0;
20. bwr.read_buffer = (unsigned) readbuf;
21.
22. // 读取 Binder 命令
23. res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
24.
25. if (res < 0) {26. ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
27. break;
28. }
29.
30. // 解析 Binder 命令,使用 func 处理
31. res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
32. if (res == 0) {33. ALOGE("binder_loop: unexpected reply?!\n");
34. break;
35. }
36. if (res < 0) {37. ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
38. break;
39. }
40. }
41.}
Service Manager 对客户端的请求是在 svcmgr_handler 函数中处理的,也就是带用 binder_loop 时传入的回调函数。请求处理代码如下。
1.---> service_manager.c
2.
3.int svcmgr_handler(struct binder_state *bs,
4. struct binder_txn *txn,
5. struct binder_io *msg,
6. struct binder_io *reply)
7.{
8. struct svcinfo *si;
9. uint16_t *s;
10. unsigned len;
11. void *ptr;
12. uint32_t strict_policy;
13. int allow_isolated;
14.
15.// ALOGI("target=%p code=%d pid=%d uid=%d\n",
16.// txn->target, txn->code, txn->sender_pid, txn->sender_euid);
17.
18. if (txn->target != svcmgr_handle)
19. return -1;
20.
21. // Equivalent to Parcel::enforceInterface(), reading the RPC
22. // header with the strict mode policy mask and the interface name.
23. // Note that we ignore the strict_policy and don't propagate it
24. // further (since we do no outbound RPCs anyway).
25. strict_policy = bio_get_uint32(msg);
26. s = bio_get_string16(msg, &len);
27. if ((len != (sizeof(svcmgr_id) / 2)) ||
28. memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {29. fprintf(stderr,"invalid id %s\n", str8(s));
30. return -1;
31. }
32.
33. switch(txn->code) {
34. // 通过字符串描述查询 Service
35. case SVC_MGR_GET_SERVICE:
36. case SVC_MGR_CHECK_SERVICE:
37. s = bio_get_string16(msg, &len);
38. ptr = do_find_service(bs, s, len, txn->sender_euid);
39. if (!ptr)
40. break;
41. bio_put_ref(reply, ptr);
42. return 0;
43.
44. // 通过字符串描述注册 Service
45. case SVC_MGR_ADD_SERVICE:
46. s = bio_get_string16(msg, &len);
47. ptr = bio_get_ref(msg);
48. allow_isolated = bio_get_uint32(msg) ? 1 : 0;
49. if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated))
50. return -1;
51. break;
52.
53. // 列出当前系统中所有已注册 Sevice 的名字
54. case SVC_MGR_LIST_SERVICES: {55. unsigned n = bio_get_uint32(msg);
56.
57. si = svclist;
58. while ((n-- > 0) && si)
59. si = si->next;
60. if (si) {61. bio_put_string16(reply, si->name);
62. return 0;
63. }
64. return -1;
65. }
66. default:
67. ALOGE("unknown code %d\n", txn->code);
68. return -1;
69. }
70.
71. bio_put_uint32(reply, 0);
72. return 0;
73.}
在进行 Binder 通信过程中,当有 server 通过 addService 函数请求注册 Service 时,Service Manager 就会得到 SVC_MGR_ADD_SERVICE 请求,调用 do_add_service 函数来完成注册。下面看一下它的实现。
1.---> service_manager.c
2.
3.int do_add_service(struct binder_state *bs,
4. uint16_t *s, unsigned len,
5. void *ptr, unsigned uid, int allow_isolated)
6.{
7. struct svcinfo *si;
8. //ALOGI("add_service('%s',%p,%s) uid=%d\n", str8(s), ptr,
9. // allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
10.
11. if (!ptr || (len == 0) || (len > 127))
12. return -1;
13.
14. // 检查注册服务的进程是否有权限
15. if (!svc_can_register(uid, s)) {16. ALOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
17. str8(s), ptr, uid);
18. return -1;
19. }
20.
21. // 检查服务是否已经被注册
22. si = find_svc(s, len);
23. if (si) {24. if (si->ptr) {25. ALOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
26. str8(s), ptr, uid);
27. svcinfo_death(bs, si);
28. }
29. si->ptr = ptr;
30. } else {
31. // 新建一个 svcinfo 对象,并加入全局链表 svclist 中
32. si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
33. if (!si) {34. ALOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
35. str8(s), ptr, uid);
36. return -1;
37. }
38. si->ptr = ptr;
39. si->len = len;
40. memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
41. si->name[len] = '\0';
42. si->death.func = svcinfo_death;
43. si->death.ptr = si;
44. si->allow_isolated = allow_isolated;
45. si->next = svclist;
46. svclist = si;
47. }
48.
49. binder_acquire(bs, ptr);
50. binder_link_to_death(bs, ptr, &si->death);
51. return 0;
52.}
addService 的时序图如下
在 Binder 通信过程中,当有 client 通过 getService 函数查询 Service 时,Service Manager 就会得到 SVC_MGR_CHECK_SERVICE 请求,调用 do_find_service 函数来完成查询。下面看一下它的实现。
1.---> service_manager.c
2.
3.void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len, unsigned uid)
4.{
5. struct svcinfo *si;
6. si = find_svc(s, len);
7.
8.// ALOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);
9. if (si && si->ptr) {10. if (!si->allow_isolated) {
11. // If this service doesn't allow access from isolated processes,
12. // then check the uid to see if it is isolated.
13. unsigned appid = uid % AID_USER;
14. if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
15. return 0;
16. }
17. }
18. return si->ptr;
19. } else {
20. return 0;
21. }
22.}
getService 的时序图如下
到此,对 Service Manager 的代码分析结束。可以认为 Service Manager 存在的重要意义在于,
●ServiceManager 能集中管理系统内的所有服务, 它能施加权限控制, 并不是任何进程都能注册服务的。
●ServiceManager 支持通过字符串名称来查找对应的 Service。
●由于各种原因的影响,Server 进程可能生死无常。如果让每个 Client 都去检测, 压力实在太大了。现在有了统一的管理机构,Client 只需要查询 ServiceManager, 就能把握动向,得到最新信息。
defaultServiceManager
Binder 的 Server 端和 Client 端在开始通信之前,都需要使用 defaultServiceManager()来获得 Service Manager 的代理对象,才能完成注册服务和查询服务的功能。下面分析 defaultServiceManager()的实现过程。代码从 IServiceManager 开始,调用到 ProcessState::getStrongProxyForHandle()。
1.---> IServiceManager.cpp
2.
3.sp<IServiceManager> defaultServiceManager()
4.{5. if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
6.
7. {8. AutoMutex _l(gDefaultServiceManagerLock);
9. while (gDefaultServiceManager == NULL) {
10. gDefaultServiceManager = interface_cast<IServiceManager>(11. // 调用 ProcessState::getContextObject()
12. ProcessState::self()->getContextObject(NULL));
13. if (gDefaultServiceManager == NULL)
14. sleep(1);
15. }
16. }
17.
18. return gDefaultServiceManager;
19.}
1.---> ProcessState.cpp
2.
3.sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
4.{5. return getStrongProxyForHandle(0);
6.}
7.
8.......
9.
10.sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
11.{
12. sp<IBinder> result;
13.
14. AutoMutex _l(mLock);
15.
16. // 查询当前进程维护的 Service 代理对象的列表
17. handle_entry* e = lookupHandleLocked(handle);
18.
19. if (e != NULL) {
20. IBinder* b = e->binder;
21. // 如果 BpBinder 不存在,就创建一个。否这直接返回
22. if (b == NULL || !e->refs->attemptIncWeak(this)) {23. if (handle == 0) {
24. // defaultServiceManager 走这里
25. Parcel data;
26. // 检查 Binder 对象是否存在
27. status_t status = IPCThreadState::self()->transact(28. 0, IBinder::PING_TRANSACTION, data, NULL, 0);
29. if (status == DEAD_OBJECT)
30. return NULL;
31. }
32.
33. // 创建一个 BpBinder,defaultServiceManager 的 handle 是 0
34. b = new BpBinder(handle);
35. e->binder = b;
36. if (b) e->refs = b->getWeakRefs();
37. result = b;
38. } else {39. result.force_set(b);
40. e->refs->decWeak(this);
41. }
42. }
43.
44. return result;
45.}
1.---> BpBinder.cpp
2.
3.// handle = 0
4.BpBinder::BpBinder(int32_t handle)
5. : mHandle(handle)
6. , mAlive(1)
7. , mObitsSent(0)
8. , mObituaries(NULL)
9.{10. ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
11.
12. extendObjectLifetime(OBJECT_LIFETIME_WEAK);
13. IPCThreadState::self()->incWeakHandle(handle);
14.}
defaultServiceManager 函数最终创建了一个 mHandle= 0 的 BpBinder 对象。这个 BpBinder 就是作为 Service Manager 的服务代理与 Service Manager 进行通讯。Binder 的通信是使用 handle 作为标识的,0 就代表 Service Manager 的 handle。