Android系统的Binder机制之一——Service Manager

Android虽然构建在Linux上面,可是在IPC(进程间)机制方面,没有利用Linux提供IPC机制,而是本身实现了一套轻量级的IPC机制——binder机制。而且Android Binder机制之上,Android框架提供了一套封装,能够实现对象代理(在本地进程中代理远程进程的对象)。本文简单分析一下Android Binder机制。服务器

Binder情景分析

    一个IPC通信咱们能够理解成客户端-服务器模式,所以咱们先在这里分析一下典型的Binder应用模式:框架

一、客户端经过某种方式(后文会详细介绍)获得服务器端的代理对象。从客户端角度看来代理对象和他的本地对象没有什么差异。它能够像其余本地对象同样调用其方法,访问其变量。 
二、客户端经过调用服务器代理对象的方法向服务器端发送请求。 
三、代理对象把用户请求经过Android内核(Linux内核)的Binder驱动发送到服务器进程。 
四、服务器进程处理用户请求,并经过Android内核(Linux内核)的Binder驱动返回处理结果给客户端的服务器代理对象。 
五、客户端收到服务器端的返回结果。
函数

    若是你对COM或者Corba熟悉的话,以上的情景是否会让你联想到什么呢?没错!都是对象代理。以上的情景,在Android中常常会被用到。若是你尚未注意到这点儿,那么本文很是适合你。oop

Binder机制的组成

一、Binder驱动

    binder是内核中的一个字符驱动设备位于:/dev/binder。这个设备是Android系统IPC的核心部分,客户端的服务代理用来经过它向服务器(server)发送请求,服务器也是经过它把处理结果返回给客户端的服务代理对象。咱们只须要知道它的功能就能够了,本文咱们的重点不在这里,因此后面不会专门介绍这部分,由于不多会有人会显示打开这个设备去开发Android程序。若是想深刻了解的话,请研究内核源码中的binder.c。ui

二、Service Manager

    负责管理服务。对应于第一步中,客户端须要向Service Manager来查询和得到所须要服务。服务器也须要向Service Manager注册本身提供的服务。能够看出Service Manager是服务的大管家。spa

三、服务(Server)

    须要强调的是这里服务是指的是System Server,而不是SDK server,请参考《(转)高焕堂——Android框架底层结构知多少?》关于两种Server的介绍(其实应该是三种,丢掉了init调用的server,在init.rc中配置)。.net

四、客户端

    通常是指Android系统上面的应用程序。它能够请求Server中的服务。代理

五、对象代理

    是指在客户端应用程序中生成的Server代理(proxy)。从应用程序角度看代理对象和本地对象没有差异,均可以调用其方法,方法都是同步的,而且返回相应的结果。unix

大内总管——Service Manager

    Android系统Binder机制的总管是Service Manager,全部的Server(System Server)都须要向他注册,应用程序须要向其查询相应的服务。可见其做用是多么的重要,因此本文首先介绍Service Manager。rest

    经过上面介绍咱们知道Service Manager很是重要,责任重大。那么怎样才能成为Service Manager呢?是否是谁均可以成为Service Manager呢?怎样处理server的注册和应用程序的查询和获取服务呢?为了回答这些问题先查看,Android中Service Manager的源码,其源码位于:

frameworks\base\cmds\servicemanager\service_manager.c

咱们发现了main函数,说明他本身就是一个进程,在init.rc中咱们发现:

service servicemanager /system/bin/servicemanager
    user system     critical
    onrestart restart zygote
    onrestart restart media

说明其是Android核心程序,开机就会自动运行。

    下面咱们在研究一下它的代码,main函数很简单:

int main(int argc, char **argv)
{
    struct binder_state *bs;
    void *svcmgr = BINDER_SERVICE_MANAGER;

    bs = binder_open(128*1024);

    if (binder_become_context_manager(bs)) {
        LOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    svcmgr_handle = svcmgr;
    binder_loop(bs, svcmgr_handler);
    return 0;
}

咱们看到它先调用binder_open打开binder设备(/dev/binder),其次它调用了binder_become_context_manager函数,这个函数使他本身变为了“Server大总管”,其代码以下:

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

也就是经过ioctl向binder设备声明“我就是server大总管”。

    Service Manager做为一个Server大总管,自己也是一个server。既然是一个server就要时刻准备为客户端提供服务。最好Service Manager调用binder_loop进入到循环状态,并提供了一个回调函数,等待用户的请求。注意他的Service Manager的客户端既包括应用程序(查询和获取服务),也包括Server(注册服务)。

    Service Manager的客户怎样才能请求其服务呢?答案是上文咱们提到的情景同样。客户须要在本身进程中建立一个服务器代理。如今没有地方去查询服务,那么怎样它的客户怎样生成他的服务代理对象呢?答案是binder设备(/devbinder)为每个服务维护一个句柄,调用binder_become_context_manager函数变为“Server大总管”的服务,他的句柄永远是0,是一个“众所周知”的句柄,这样每一个程序均可以经过binder机制在本身的进程空间中建立一个

Service Manager代理对象了。其余的服务在binder设备在设备中的句柄是不定的,须要向“Server大总管”查询才能知道。

    如今咱们须要研究Server怎样注册服务了,仍是在其源码中,咱们能够看到在其服务处理函数中(上文提到binder_loop函数注册给binder设备的回调函数)有以下代码:

case SVC_MGR_ADD_SERVICE:
        s = bio_get_string16(msg, &len);
        ptr = bio_get_ref(msg);
        if (do_add_service(bs, s, len, ptr, txn->sender_euid))
            return -1;
        break;

有server向binder设备写入请求注册Service时,Service Manager的服务处理回调函数将会被调用。咱们在仔细看看do_add_service函数的实现:

int do_add_service(struct binder_state *bs,
                   uint16_t *s, unsigned len,
                   void *ptr, unsigned uid)
{
    struct svcinfo *si;// LOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);     if (!ptr || (len == 0) || (len > 127))
        return -1;

    if (!svc_can_register(uid, s)) {
        LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
             str8(s), ptr, uid);
        return -1;
    }

    si = find_svc(s, len);
    if (si) {
        if (si->ptr) {
            LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",
                 str8(s), ptr, uid);
            return -1;
        }
        si->ptr = ptr;
    } else {
        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
        if (!si) {
            LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
                 str8(s), ptr, uid);
            return -1;
        }
        si->ptr = ptr;
        si->len = len;
        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
        si->name[len] = '\0';
        si->death.func = svcinfo_death;
        si->death.ptr = si;
        si->next = svclist;
        svclist = si;
    }

    binder_acquire(bs, ptr);
    binder_link_to_death(bs, ptr, &si->death);
    return 0;
}

咱们看到首先检查是否有权限注册service,没权限就对不起了,出错返回;而后检查是否已经注册过,注册过的service将不能再次注册。而后构造一个svcinfo对象,并加入一个全局链表中svclist中。最后通知binder设备:有一个service注册进来

    咱们再来看看客户端怎样经过Service Manager得到Service,仍是在服务处理函数中(上文提到binder_loop函数注册给binder设备的回调函数)有以下代码:

case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        ptr = do_find_service(bs, s, len);
        if (!ptr)
            break;
        bio_put_ref(reply, ptr);
        return 0;

    咱们能够看到经过do_find_service查找Service若是查找到的话,写入reply中返回给客户端。

    本文咱们简单分析了一下Service Manager,后续咱们会继续分析Android binder机制的其余部分。

相关文章
相关标签/搜索