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。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。