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的世界。 

未完,待续。。。

更多相关文章

  1. 《Android(安卓)Dev Guide》系列教程5:Android进程和线程
  2. Android漫游记(1)---内存映射镜像(memory maps)
  3. android eclipse 真机调试
  4. 为Android内核添加新驱动,并添加到menuconfig菜单【实践简记】
  5. Android核心模块及相关技术(自IT168)
  6. mk中的android:sharedUserId和LOCAL_CERTIFICATE作用
  7. Android启动过程深入解析
  8. Android(安卓)IPC 通讯机制源码分析
  9. Android进程间通信 — AIDL

随机推荐

  1. 详解MySQL的Seconds_Behind_Master
  2. MySQL InnoDB架构的相关总结
  3. MySQL 独立索引和联合索引的选择
  4. MySQL数据表分区策略及优缺点分析
  5. MySQL高级特性——数据表分区的概念及机
  6. MySQL 慢日志相关知识总结
  7. MySQL优化之如何写出高质量sql语句
  8. mysql数据库入门第一步之创建表
  9. MySQL 隔离数据列和前缀索引的使用总结
  10. MySQL 使用自定义变量进行查询优化