ServiceManager

来源:互联网 发布:淘宝如何使用电子面单 编辑:程序博客网 时间:2024/06/05 17:31
      ServiceManager层次基本如下,java空间的Service Manager类与Native空间的功能并不完全对应,java层的Service Manager类的实现最终是通过BinderProxy传递给Native层来完成的。
       

     Service Manager存在的意义
1. Service Manager能集中管理系统内的所有服务,它能被施加权限控制,并不是任何进程都能注册服务的。
2. Service Manager支持通过字符串名称来查找对应的Service。
3. 由于各种原因的影响,Server进程可能生死无常。如果有了Service Manager做统一的管理,那么Client只要向Service Manager做查询,就能得到Server的最新信息。
 

1 ServiceManager启动  

     在init.rc中servicemanager是作为native服务启动的。 
service servicemanager /system/bin/servicemanagerclass coreuser systemgroup systemcriticalonrestart restart zygoteonrestart restart mediaonrestart restart surfaceflingeronrestart restart drm


2 Native空间ServiceManager的工作内容

2.1 servicemanager#main
        mian函数源码位置在frameworks/base/cmds/servicemanager/service_manager.c,如下:
int main(int argc, char **argv){struct binder_state *bs;//宏:#define BINDER_SERVICE_MANAGER ((void*)0)。表示ServiceManager对应的句柄为0,表面自己是服务器管理者。其他的Server进程句柄值都是大于0的。void *svcmgr = BINDER_SERVICE_MANAGER;//打开Binder设备,映射128K的内存地址空间bs = binder_open(128*1024);//告诉Binder驱动程序自己是Binder上下文管理者if (binder_become_context_manager(bs)) {ALOGE("cannot become context manager (%s)\n", strerror(errno));return -1;}//ServiceManager对应的句柄赋值svcmgr_handle = svcmgr;//进入一个无线循环,充当server角色,等待Client的请求binder_loop(bs, svcmgr_handler);return 0;}

从main函数中可以看出,它主要做了三件事情:

(1)打开/dev/binder设备,并在内存中映射128K的空间。
struct binder_state *binder_open(unsigned mapsize)  {      struct binder_state *bs;        bs = malloc(sizeof(*bs));      if (!bs) {          errno = ENOMEM;          return 0;      }        bs->fd = open("/dev/binder", O_RDWR);      if (bs->fd < 0) {          fprintf(stderr,"binder: cannot open device (%s)\n",                  strerror(errno));          goto fail_open;      }        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 0;  }  

(2)通知Binder设备,把自己变成context_manager
int binder_become_context_manager(struct binder_state *bs){    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);}

(3)进入循环,不停的去读Binder设备,看是否有对service的请求,如果有的话,就去调用svcmgr_handler函数回调处理请求。
void binder_loop(struct binder_state *bs, binder_handler func)  {      int res;      /*         binder_write_read结构用来应用层和驱动层传递数据。         struct binder_write_read {             signed long write_size;             signed long write_consumed;             unsigned long write_buffer;             signed long read_size;             signed long read_consumed;             unsigned long read_buffer;         };     */          struct binder_write_read bwr;          unsigned readbuf[32];            bwr.write_size = 0;          bwr.write_consumed = 0;          bwr.write_buffer = 0;            // 通知binder驱动,我要开始循环接受消息了。          readbuf[0] = BC_ENTER_LOOPER;          binder_write(bs, readbuf, sizeof(unsigned));            // 开始循环接收数据          for (;;) {              bwr.read_size = sizeof(readbuf);              bwr.read_consumed = 0;              bwr.read_buffer = (unsigned) readbuf;                    // 通过ioctl获得驱动中的数据              res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);                if (res < 0) {                      ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));                      break;              }                    // 获得之后开始解析处理              res = binder_parse(bs, 0, readbuf, bwr.read_consumed, 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;              }          }  }  
2.2 UML类图



3 java空间ServiceManger的工作内容

3.1 UML类图


(1)ServiceManager:通过getIServiceManager方法获取的是ServiceManagerProxy对象; ServiceManager的addService, getService实际工作都交由ServiceManagerProxy的相应方法来处理;
(2)ServiceManagerProxy:其成员变量mRemote指向BinderProxy对象,ServiceManagerProxy的addService, getService方法最终是交由mRemote来完成。
(3)ServiceManagerNative:其方法asInterface()返回的是ServiceManagerProxy对象,ServiceManager便是借助ServiceManagerNative类来找到ServiceManagerProxy;
(4)Binder:其成员变量mObject和方法execTransact()用于native方法
(5)BinderInternal:内部有一个GcWatcher类,用于处理和调试与Binder相关的垃圾回收。
(6)IBinder:接口中常量FLAG_ONEWAY:客户端利用binder跟服务端通信是阻塞式的,但如果设置了FLAG_ONEWAY,这成为非阻塞的调用方式,客户端能立即返回,服务端采用回调方式来通知客户端完成情况。另外IBinder接口有一个内部接口DeathDecipient(死亡通告)。
          
ServiceManager.addService方法
public static void addService(String name, IBinder service, boolean allowIsolated) {    try {        getIServiceManager().addService(name, service, allowIsolated);     } catch (RemoteException e) {        Log.e(TAG, "error in addService", e);    }}
       先看getIServiceManager
    private static IServiceManager getIServiceManager() {        if (sServiceManager != null) {            return sServiceManager;        }        // Find the service manager        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());        return sServiceManager;    }
     ServiceManager.getIServiceManager最终等价于new ServiceManagerProxy(new BinderProxy());framework层的ServiceManager的调用实际的工作确实交给远程接口ServiceManagerProxy的成员变量BinderProxy;而BinderProxy通过jni方式,最终会调用BpBinder对象;可见上层binder架构的核心功能基本都是靠native架构的服务来完成的。

4、Java空间与Native空间中ServiceManager的连接

       从上面的分析来看,native空间与java空间的ServiceManager似乎没有什么联系,那java空间的ServiceManager代理是如何访问到native空间的ServiceManager服务呢?实际上,在Zygote进程中,先创建了虚拟机,然后注册了一系列的jni函数,其中有一个函数就是:REG_JNI(register_android_os_Binder),在这函数中会注册一个BinderInternal类,在这个类中有一个原生函数:
{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
      android_os_BinderInternal_getContextObject源码如下:
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz){    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);//等价于 new BpBinder(0);    return javaObjectForIBinder(env, b);}
      这里就相当于找到了binder链表中的ServiceManager的代理。当我们在使用ServiceManager的getIServiceManager()接口时,代码如下:
    private static IServiceManager getIServiceManager() {        if (sServiceManager != null) {            return sServiceManager;        }        // Find the service manager  等价于new ServiceManagerProxy(new BinderProxy())         sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());        return sServiceManager;    }
      进而就可以call到binder驱动中,找到远程的ServiceManager的stub。







如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
0 0