ServiceManager进程

ServiceManager进程

Posted by candy1126xx on March 12, 2017

简介

ServiceManager进程是由init进程创建的。源码文件是service_native.c。它是Native层的、系统全局“服务端”的管理者。

每个应用进程和SystemServer进程都有1个ServiceManager对象。它以单例模式封装了ServiceManagerNative对象,提供对系统服务的“服务端”的缓存,并封装了向ServiceManager进程申请“服务端”的过程。

启动后做了些什么?

  1. 创建一个binder_state结构体;
  2. 系统调用open,以可读可写(O_RDWR)模式打开文件”/dev/binder”,返回“文件描述符”到binder_state -> fd;
  3. 创建一个binder_proc结构体保存Binder机制的全局信息;
  4. 系统调用ioctl(BINDER_VERSION),设置Binder Version;
  5. binder_state -> mapsize = 128*1024;
  6. 系统调用mmap,把binder_state -> fd映射到内存,返回“映射区地址“到binder_state -> mapped;
  7. 系统调用ioctl(BINDER_SET_CONTEXT_MGR),把Zygote进程设置为守护进程;
  8. 系统调用ioctl(BINDER_WRITE_READ),写入BC_ENTER_LOOP,告诉Binder驱动开始循环;
  9. 开始循环,在一次循环中有两步操作:第一步从Binder驱动读出一个binder_write_read;第二步解析这个binder_write_read,执行相应操作。

服务端注册到ServiceManager

以MediaService为例

1.获取ServiceManager对象在MediaService进程的客户端

在IServiceManager.cpp -> defaulteServiceManager():

  1. gDefaulteServiceManager是定义在Static.cpp中的单例;如果gDefaulteServiceManager不为null,直接返回;否则调用interface_cast(ProcessState::self() -> getContextObject(NULL))创建。
  2. ProcessState::self() -> getContextObject(NULL)会返回一个句柄为0的BpBinder,即ServiceManager在通信层的客户端。
  3. 调用BpBinder.queryLocalInterface()获取ServiceManager业务层客户端在MediaService进程的实例,不为null则返回实例的指针;否则以BpBinder为参数创建一个BpServiceManager实例,并返回它的指针。

至此,MediaService进程有了一个指向BpServiceManager实例的指针。客户端向ServiceManager发送信息,相当于调用BpServiceManager的方法 ,转调BpBinder -> transtact(),转调IPCThreadState::self() -> transact()。

2.MediaService进程向Binder驱动写入数据

调用BpServiceManager -> addService(),转调BpBinder -> transtact(ADD_SERIVCE_TRANSACTION),转调IPCThreadState::self() -> transact():

  1. 向mOut写入指令吗BC_TRANSACTION;
  2. 创建一个binder_transaction_data,其中target.handle = 0,代表ServiceManager进程的句柄;code = ADD_SERIVCE_TRANSACTION,请求码;data_xxx 写入了三样: IServiceManager -> getInterfaceDescriptor()、name即“android.os.service_manager”、指向位于MediaService进程中的MediaService服务端的指针;
  3. 把binder_transaction_data写入mOut;
  4. 创建一个binder_write_read,其中“写”的部分为mOut,“读”的部分为mIn;
  5. 系统调用ioctl(BINDER_WRITE_READ),写入binder_write_read;

至此,MediaService进程向Binder驱动写入了一个binder_write_read。

3.ServiceManager进程从Binder驱动读出数据

数据是一个binder_write_read,其中指令码为BR_TRANSACTION,请求码为SVC_MGR_ADD_SERVICE。

  1. 转调service_manager.c -> do_add_service();
  2. 检测要注册的服务是否可以被添加到ServiceManager;只有当操作者是root或system进程,或者被添加的服务在allowed中定义过,才能被添加;
  3. 搜索svclist,看服务是否已经存在;如果不存在,创建svcinfo,并添加到svclist。

至此,service_manager.c -> svclist多了一个svcinfo,其中,handle为???,name为“android.os.service_manager”。

应用进程获取系统服务的服务端

在[Java]ServiceManager.getService()中:

  1. 查询缓存sCache中是否有服务名对应的”客户端”,如果有直接返回;
  2. 否则,获取ServiceManagerNative.ServiceManagerProxy的单例,调用它的getService();
  3. 在ServiceManagerProxy.getService()中,调用BpBinder.transact(),转入Native层;
  4. 向ServiceManager的缓冲区中写数据,其中请求码为GET_SERVICE_TRANSACTION,InterfaceToken为“android.os.IServiceManager“,参数为要请求的服务名;
  5. ServiceManager进程从Binder驱动读出一个binder_write_read,转调service_manager.c -> do_find_service();
  6. 搜索svclist,按name找到对应的scvinfo,并用scvinfo -> handle转换出一个指向BpBinder的指针,写入reply(Parcel)。
  7. 回到应用进程Java层,调用Parcel.nativeReadStrongBinder()从reply中读出IBinder对象,即为所需客户端;
  8. 把服务名、客户端存入缓存。