Binder之Service-Manager

5次阅读

共计 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。

正文完
 0