Binder之Service Manager

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之Service Manager_第1张图片

在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的时序图如下
Binder之Service Manager_第2张图片
到此,对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 defaultServiceManager()
4.{
5.    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
6.    
7.    {
8.        AutoMutex _l(gDefaultServiceManagerLock);
9.        while (gDefaultServiceManager == NULL) {
10.            gDefaultServiceManager = interface_cast(
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 ProcessState::getContextObject(const sp& caller)
4.{
5.    return getStrongProxyForHandle(0);
6.}
7. 
8.......
9. 
10.sp ProcessState::getStrongProxyForHandle(int32_t handle)
11.{
12.    sp 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。

你可能感兴趣的:(c,android,binder)