Android Binder机制之 ServiceManager的启动

Android Binder机制的ServiceManager

    对于Android 来说,Binder进程间的通信机制几乎无处不在,可以说是整个Android系统中各个组件之间交互的灵魂。所以,想要深入的理解Android 中进程间通信的机制,还是需要对Binder机制有一个深入的研究的。

    Binder机制很复杂,设计到的东西特别多,很难一下将这些东西说清楚,到期该从何说起呢?不防就从Binder服务的管理者ServiceManger开始说起吧。

    servicemanager是一个独立的进程,在Android系统启动的时候有init.rc脚本,启动脚本如下:

service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onerestart zygote
    onerestart media
    onerestart surfaceflinger
    ...

   有必要对上面的启动脚本进行解释一下子:

service servicemanager 表示该进程是以服务的形式运行的

class core 表示这个是核心服务

critical 表示很重要

onerestart zygote 表示该服务重启,需要重启zygote进程(后面的含义是一样的)。

Android 系统启动servicemanager之后,是让它不停地干活的,具体干什么活呢?既然是名字叫做ServiceManager,那么它既是用来管理系统service的,具体来说有两个功能1. addService ,即注册一个服务到系统中 2. getService,即返回服务的代理对象。对于这个两个功能的实现,且看servicemanager的main函数

代码路径为:frameworks/base/cmds/servicemanager/service_manager.c

int main(int argc, char **argv)
{
    struct binder_state *bs; //ServiceManager的描述
    bs = binder_open(128*1024);  //关键点1
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }

    if (binder_become_context_manager(bs)) { //关键点2
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }
    ...  //中间为selinux相关代码, 和主题无关
    //进入Binder 的loop中
    binder_loop(bs, svcmgr_handler); //关键点3

    return 0;
}

对于main函数中标记的关键点做出解释:

1. binder_open:

    总的来说binder_open 干了三件事情:1. 打开/dev/binder 获得句柄值 2. 通过ioctl 查询Binder版本 3.映射地址空间

且看源码:

struct binder_state *binder_open(size_t mapsize)
{
    struct binder_state *bs;
    struct binder_version vers;

    bs = malloc(sizeof(*bs));
    if (!bs) {
        errno = ENOMEM;
        return NULL;
    }
    //1. 打开驱动
    bs->fd = open("/dev/binder", O_RDWR);
    if (bs->fd < 0) {
        fprintf(stderr,"binder: cannot open device (%s)\n",
                strerror(errno));
        goto fail_open;
    }
    //2. ioctl
    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
        fprintf(stderr,
                "binder: kernel driver version (%d) differs from user space version (%d)\n",
                vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
        goto fail_open;
    }
    //通过mmap将空间映射到用户空间
    bs->mapsize = mapsize;
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
    if (bs->mapped == MAP_FAILED) {
        fprintf(stderr,"binder: cannot map device (%s)\n",
                strerror(errno));
        goto fail_map;
    }

    return bs;

fail_map:
    close(bs->fd);
fail_open:
    free(bs);
    return NULL;
}

2. binder_become_context_manager

int binder_become_context_manager(struct binder_state *bs)
{
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

上面代码比较明显,即是通过ioctl来让servicemanger成为服务管理中心,并设置handle为0(这个0很重要,后续分析)

3. binder_loop

servicemanager将在这里完成系统交给它的使命:对service进行注册和返回其代理对象。

binder_loop(bs, svcmgr_handler); //bs携带者servicemanager的信息,svcmgr_handler则是一个回调函数
void binder_loop(struct binder_state *bs, binder_handler func)
{
    int res;
    struct binder_write_read bwr;
    uint32_t readbuf[32];

    bwr.write_size = 0;
    bwr.write_consumed = 0;
    bwr.write_buffer = 0;

    readbuf[0] = BC_ENTER_LOOPER;
    binder_write(bs, readbuf, sizeof(uint32_t));  //告知binder驱动,servicemanager进入loop循环

    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;

        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); //从binder驱动中读取数据

        if (res < 0) {
            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
            break;
        }

        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); //解析数据,并传递func回调函数
        if (res == 0) {
            ALOGE("binder_loop: unexpected reply?!\n");
            break;
        }
        if (res < 0) {
            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
            break;
        }
    }
}

上面的binder_loop循环会不断的通过ioctl从binder驱动中读取数据,并解析执行。在binder_parse中会解析出从binder驱动中读取的命令,然后通过servicemanager中注册的回调函数svcmgr_handler来执行具体的指令

int svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data *txn,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
    struct svcinfo *si;
    uint16_t *s;
    size_t len;
    uint32_t handle;
    uint32_t strict_policy;
    int allow_isolated;

    //一些条件判定的逻辑操作,这里省略
    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE: //Client组件请求获取Service代理对象的请求
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid); //执行getService操作
        if (!handle)
            break;
        bio_put_ref(reply, handle); //将handle写入驱动
        return 0;
    case SVC_MGR_ADD_SERVICE: //Service请求注册到ServiceManager中
        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,  //执行addService的操作
            allow_isolated, txn->sender_pid))
            return -1;
        break;
    case SVC_MGR_LIST_SERVICES: {   //查询所有的service操作
        uint32_t n = bio_get_uint32(msg);
        if (!svc_can_list(txn->sender_pid)) {
            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;
}

首先看addService的请求操作

int do_add_service(struct binder_state *bs,
                   const uint16_t *s, size_t len,
                   uint32_t handle, uid_t uid, int allow_isolated,
                   pid_t spid)
{//servicemanager中通过一个链表来维护所有注册进来的service组件
    struct svcinfo *si; //svcinfo 是service链表的一个节点
    //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
    //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);

    if (!handle || (len == 0) || (len > 127))
        return -1;

    if (!svc_can_register(s, len, spid, uid)) {  //检测该service是否可以进行注册到ServiceManager
        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
             str8(s, len), handle, uid);
        return -1;
    }

    si = find_svc(s, len);
    if (si) { //如果已经注册了,将不再注册
        if (si->handle) {
            ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
                 str8(s, len), handle, uid);
            svcinfo_death(bs, si);
        }
        si->handle = handle;
    } else { //开始将service注册到ServiceManager中
        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
        if (!si) {
            ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
                 str8(s, len), handle, uid);
            return -1;
        }
        si->handle = handle;
        si->len = len;
        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
        si->name[len] = '\0';
        si->death.func = (void*) svcinfo_death;
        si->death.ptr = si;
        si->allow_isolated = allow_isolated;
        si->next = svclist;
        svclist = si;
    }

    binder_acquire(bs, handle);  //将service注册到binder驱动中, 通过binder_write 将命令写入binder驱动
    binder_link_to_death(bs, handle, &si->death);
    return 0;
}

getService和addService很相似,这里就不再贴代码了。 getService时也是通过查询ServiceManager维护的链表,然后返回其handle。好像getService时没有和binder驱动进行交互(但是binder驱动的引用计数和这个也关系的)。

到这里ServiceManager进行的启动大的大致过程讲完了,但是这里还有很多细节问题的问题是没有说到的。亲爱的读者,你有没有发现,ServiceManager进程确实是实现了对service组件的管理,ServiceManager进程现在还没有提供任何进行addService和getService的接口。在Native层要注册addService或者getSerivce是通过IServiceManager接口进行的,IServiceManager接口到底是怎么和servicemanager进程之间建立联系的。以及,当前仅仅介绍了servicemanager进程启动,还没有真正的进入binder的世界。 

未完,待续。。。

你可能感兴趣的:(Android,Binder,进程间通信)