addService实例分析

这个例子源自ActivityManagerService(AMS),我们通过它揭示Java层Binder的工作原理。该例子的分析步骤如下:
首先分析AMS如何将自己注册到ServiceManager。
然后分析AMS如何响应客户端的Binder调用请求。
本例的起点是setSystemProcess函数,其代码如下所示:
[-->ActivityManagerService.java::setSystemProcess]
public static void setSystemProcess() {
 try {
      ActivityManagerService m = mSelf;
      //将ActivityManagerService服务注册到ServiceManager中
      ServiceManager.addService("activity", m);
      ......//省略后续内容
    }
 ......
 return;
}
上面所示代码行的目的是将AMS服务注册到ServiceManager中。AMS是Android核心服务中的核心,以后我们会经常和它打交道。
大家知道,整个Android系统中有一个Native的ServiceManager(以后简称SM)进程,它统筹管理Android系统上的所有Service。成为一个Service的必要条件是在SM中注册。下面来看Java层的Service是如何在SM中注册的。
1. 在SM中注册服务
(1) 创建ServiceManagerProxy
在SM中注册服务的函数为addService,其代码如下:
[-->ServiceManager.java::addService]
public static void addService(String name, IBinder service) {
try {
        //getIServiceManager返回什么
       getIServiceManager().addService(name, service);
   }
   ......
 }
//分析getIServiceManager函数
private static IServiceManager getIServiceManager() {
  ......
  //调用asInterface,传递的参数类型为IBinder       
  sServiceManager = ServiceManagerNative.asInterface(
                      BinderInternal.getContextObject());
  return sServiceManager;
}
asInterface的参数为BinderInternal.getContextObject的返回值。这是一个native的函数,其实现的代码为:
[-->android_util_Binder.cpp::android_os_BinderInternal_getContextObject]
static jobject android_os_BinderInternal_getContextObject(
               JNIEnv* env, jobject clazz)
{
 /*
  下面这句代码,我们在卷I第6章详细分析过,它将返回一个BpProxy对象,其中
  NULL(即0,用于标识目的端)指定Proxy通信的目的端是ServiceManager
 */
  sp<IBinder>b = ProcessState::self()->getContextObject(NULL);
  //由Native对象创建一个Java对象,下面分析该函数
  return javaObjectForIBinder(env, b);
}
[-->android_util_Binder.cpp::javaObjectForIBinder]
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
 //mProxyLock是一个全局的静态CMutex对象
  AutoMutex _l(mProxyLock);
 
  /*
  val对象实际类型是BpBinder,读者可自行分析BpBinder.cpp中的findObject函数。
  事实上,在Native层的BpBinder中有一个ObjectManager,它用来管理在Native BpBinder
  上创建的Java BpBinder对象。下面这个findObject用来判断gBinderProxyOffsets
  是否已经保存在ObjectManager中。如果是,那就需要删除旧的object
  */
 jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
  if (object != NULL) {
      jobject res = env->CallObjectMethod(object, gWeakReferenceOffsets.mGet);
      android_atomic_dec(&gNumProxyRefs);
      val->detachObject(&gBinderProxyOffsets);
      env->DeleteGlobalRef(object);
  }
 
   //创建一个新的BinderProxy对象,并注册到Native BpBinder对象的ObjectManager中
      object = env->NewObject(gBinderProxyOffsets.mClass,
                          gBinderProxyOffsets.mConstructor);
  if (object != NULL) {
      env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get());
      val->incStrong(object);
      jobject refObject = env->NewGlobalRef(
              env->GetObjectField(object, gBinderProxyOffsets.mSelf));
      /*
      将这个新创建的BinderProxy对象注册(attach)到BpBinder的ObjectManager中,
      同时注册一个回收函数proxy_cleanup。当BinderProxy对象撤销(detach)的时候,
      该函数会被调用,以释放一些资源。读者可自行研究proxy_cleanup函数
      */
      val->attachObject(&gBinderProxyOffsets, refObject,
                            jnienv_to_javavm(env), proxy_cleanup);
 
      // DeathRecipientList保存了一个用于死亡通知的list
      sp<DeathRecipientList>drl = new DeathRecipientList;
      drl->incStrong((void*)javaObjectForIBinder);
      //将死亡通知list和BinderProxy对象联系起来
      env->SetIntField(object, gBinderProxyOffsets.mOrgue,
                           reinterpret_cast<jint>(drl.get()));
      //增加该Proxy对象的引用计数
      android_atomic_inc(&gNumProxyRefs);
      //下面这个函数用于垃圾回收。创建的Proxy对象一旦超过200个,该函数
      //将调用BinderInter类的ForceGc做一次垃圾回收
      incRefsCreated(env);
  }
 
  return object;
}
BinderInternal.getContextObject该函数完成了以下两个工作:
创建了一个Java层的BinderProxy对象。
通过JNI,该BinderProxy对象和一个Native的BpProxy对象挂钩,而该BpProxy对象的通信目标就是ServiceManager。
大家还记得Native层Binder中那个著名的interface_cast宏吗?在Java层中,虽然没有这样的宏,但是定义了一个类似的函数asInterface。下面来分析ServiceManagerNative类的asInterface函数,其代码如下:
[-->ServiceManagerNative.java::asInterface]
static public IServiceManager asInterface(IBinder obj)
 {
      ...... //以obj为参数,创建一个ServiceManagerProxy对象
      return new ServiceManagerProxy(obj);
}
上面的代码和Native层interface_cast非常类似,都是以一个BpProxy对象为参数构造一个和业务相关的Proxy对象,例如这里的ServiceManagerProxy对象。Service-ManagerProxy对象的各个业务函数会将相应请求打包后交给BpProxy对象,最终由BpProxy对象发送给Binder驱动以完成一次通信。
提示 实际上BpProxy也不会和Binder驱动交互,真正和Binder驱动交互的是IPCThreadState。
(2)addService函数分析
现在来分析ServiceManagerProxy的addService函数,其代码如下:
[-->ServiceManagerNative.java::addService]
public void addService(String name, IBinder service)
                         throws RemoteException {
      Parcel data = Parcel.obtain();
      Parcel reply = Parcel.obtain();
      data.writeInterfaceToken(IServiceManager.descriptor);
      data.writeString(name);
      //注意下面这个writeStrongBinder函数,后面我们会详细分析它
      data.writeStrongBinder(service);
      //mRemote实际上就是BinderProxy对象,调用它的transact,将封装好的请求数据
     //发送出去
      mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
      reply.recycle();
      data.recycle();
}
BinderProxy的transact是一个native函数,其实现代码如下:
[-->android_util_Binder.cpp::android_os_Binder Proxy_transact]
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
                                          jint code, jobject dataObj,
                                          jobject replyObj, jint flags)
{
      ......
  //从Java的Parcel对象中得到Native的Parcel对象
  Parcel* data = parcelForJavaObject(env, dataObj);
  if (data == NULL) {
      return JNI_FALSE;
  }
  //得到一个用于接收回复的Parcel对象
  Parcel* reply = parcelForJavaObject(env, replyObj);
  if (reply == NULL && replyObj != NULL) {
      return JNI_FALSE;
  }
  //从Java的BinderProxy对象中得到之前已经创建好的那个Native的BpBinder对象
  IBinder* target = (IBinder*)
      env->GetIntField(obj, gBinderProxyOffsets.mObject);
  ......
  //通过Native的BpBinder对象,将请求发送给ServiceManager
  status_t err = target->transact(code, *data, reply, flags);
  ......
  signalExceptionForError(env, obj, err);
  return JNI_FALSE;
}
看了上面的代码你会发现,Java层的Binder架构最终还是要借助Native的Binder架构进行通信。
  关于Binder架构,笔者有一个体会愿和读者一起讨论分析。
  从架构的角度看,在Java中搭建了一整套框架,如IBinder接口、Binder类和BinderProxy类。但是从通信角度看,架构的编写不论采用的是Native语言还是Java语言,只要把请求传递到Binder驱动就可以了,所以通信的目的是向binder发送请求和接收回复。在这个目的之上,考虑到软件的灵活性和可扩展性,于是编写了一个架构。反过来说,也可以不使用架构(即没有使用任何接口、派生之类的东西)而直接和binder交互,例如,ServiceManager作为Binder架构的一个核心程序,就是直接读取/dev/binder设备,获取并处理请求。从这一点上看,Binder架构的目的虽是简单的(即打开binder设备,然后读请求和写回复),但是架构是复杂的(编写各种接口类和封装类等)。我们在研究 源码时,一定要先搞清楚目的。实现只不过是达到该目的的一种手段和方式。脱离目的而去研究实现,如缘木求鱼,很容易偏离事物本质。
在对addService进行分析时,我们曾提示writeStrongBinder是一个特别的函数。那么它特别在哪里呢?我们后边会进行介绍。
(3)Binder、JavaBBinderHolder和JavaBBinder
ActivityManagerService从ActivityManagerNative类派生,并实现了一些接口,其中和Binder架构相关的只有这个ActivityManagerNative类,其原型如下:
[-->ActivityManagerNative.java]
public abstract class ActivityManagerNative
                        extends Binder
                        implements IActivityManager
ActivityManagerNative从Binder派生,并实现了IActivityManager接口。下面来看ActivityManagerNative的构造函数:
[-->ActivityManagerNative.java]
public ActivityManagerNative() {
      attachInterface(this, descriptor);//该函数很简单,读者可自行分析
  }
//这是ActivityManagerNative父类的构造函数,即Binder的构造函数
public Binder() {
      init();
}
Binder构造函数中会调用native的init函数,其实现的代码如下:
[-->android_util_Binder.cpp::android_os_Binder_init]
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
  //创建一个JavaBBinderHolder对象
  JavaBBinderHolder* jbh = new JavaBBinderHolder();
   bh->incStrong((void*)android_os_Binder_init);
 //将这个JavaBBinderHolder对象保存到Java Binder对象的mObject成员中
  env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);
}
从上面代码可知,Java的Binder对象将和一个Native的JavaBBinderHolder对象相关联。JavaBBinderHolder的定义如下:
[-->android_util_Binder.cpp]
class JavaBBinderHolder : public RefBase
{
public:
  sp<JavaBBinder>get(JNIEnv* env, jobject obj)
  {
      AutoMutex _l(mLock);
      sp<JavaBBinder>b = mBinder.promote();
      if (b == NULL) {
         //创建一个JavaBBinder,obj实际上是Java层中的Binder对象
          b = new JavaBBinder(env, obj);
          mBinder = b;
     }
      return b;
  }
  ......
private:
  Mutex           mLock;
  wp<JavaBBinder>mBinder;
};
从派生关系上可以发现,JavaBBinderHolder仅从RefBase派生,所以它不属于Binder家族。Java层的Binder对象为什么会和Native层的一个与Binder家族无关的对象绑定呢?仔细观察JavaBBinderHolder的定义可知:JavaBBinderHolder类的get函数中创建了一个JavaBBinder对象,这个对象就是从BnBinder派生的。
那么,这个get函数是在哪里调用的?答案在下面这句代码中:
//其中,data是Parcel对象,service此时还是ActivityManagerService
data.writeStrongBinder(service);
writeStrongBinder会做一个替换工作,下面是它的native代码实现:
[-->android_util_Binder.cpp::android_os_Parcel_WriteStrong Binder]
static void android_os_Parcel_writeStrongBinder(JNIEnv* env,
                                             jobject clazz, jobject object)
{
 //parcel是一个Native的对象,writeStrongBinder的真正参数是
//ibinderForJavaObject的返回值
const status_t err = parcel->writeStrongBinder(
                                  ibinderForJavaObject(env, object));
}
[-->android_util_Binder.cpp::ibinderForJavaObject]
sp<IBinder>ibinderForJavaObject(JNIEnv* env, jobject obj)
{
 //如果Java的obj是Binder类,则首先获得JavaBBinderHolder对象,然后调用
//它的get函数。而这个get函数将返回一个JavaBBinder
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
   JavaBBinderHolder* jbh = (JavaBBinderHolder*)env->GetIntField(obj,
                                    gBinderOffsets.mObject);
      return jbh != NULL ? jbh->get(env, obj) : NULL;
  }
  //如果obj是BinderProxy类,则返回Native的BpBinder对象
  if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
      return (IBinder*)
          env->GetIntField(obj, gBinderProxyOffsets.mObject);
  }
 return NULL;
}
通过上面的介绍你会发现,addService实际添加到Parcel的并不是AMS本身,而是一个名为JavaBBinder的对象。addService正是该JavaBBinder对象最终传递到Binder驱动。
读者此时容易想到,Java层中所有的Binder对应的都是这个JavaBBinder。当然,不同的Binder对象对应不同的JavaBBinder对象。

图2-2展示了Binder、JavaBBinderHolder和Java-BBinder的关系。

由图2-2可知:
Java层的Binder通过mObject指向一个Native层的JavaBBinderHolder对象。
Native层的JavaBBinderHolder对象通过mBinder成员变量指向一个Native的Java-BBinder对象。
Native的JavaBBinder对象又通过mObject变量指向一个Java层的Binder对象。
为什么不直接让Java层的Binder对象指向Native层的JavaBBinder对象呢?由于缺乏设计文档,这里不便妄加揣测,但从JavaBBinderHolder的实现上来分析,估计和垃圾回收(内存管理)有关,因为JavaBBinderHolder中的mBinder对象的类型被定义成弱引用wp了。
建议 对此,如果读者有更好的解释,不妨登录笔者的博客与大家分享一下。另外,读者务必 阅读“卷I”第6章以搞清楚ServiceManager最终是如何处理addService请求的。
2. ActivityManagerService响应请求
初见JavaBBinder时,你可能多少有些吃惊。回想一下Native层的Binder架构:虽然在代码中调用的是Binder类提供的接口,但其对象却是一个实际的服务端对象,例如MediaPlayerService对象、AudioFlinger对象。
而Java层的Binder架构中,JavaBBinder却是一个和业务完全无关的对象。那么,这个对象如何实现不同业务呢?为回答此问题,我们必须看它的onTransact函数。当收到请求时,系统会调用这个函数。
关于这个问题,建议读者 阅读卷I“第6章深入理解Binder”。
[-->android_util_Binder.cpp::onTransact]
virtual status_t onTransact(
      uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
      JNIEnv* env = javavm_to_jnienv(mVM);
      IPCThreadState* thread_state = IPCThreadState::self();
      .......
     //调用Java层Binder对象的execTransact函数
      jboolean res = env->CallBooleanMethod(mObject,
                   gBinderOffsets.mExecTransact,code,
                  (int32_t)&data, (int32_t)reply, flags);
      ......
      return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}
就本例而言,上面代码中的mObject就是ActivityManagerService,现在调用它的exec-Transact函数,该函数在Binder类中实现,具体代码如下:
 [-->Binder.java::execTransact]
private boolean execTransact(int code, int dataObj, int replyObj,int flags) {
      Parcel data = Parcel.obtain(dataObj);
      Parcel reply = Parcel.obtain(replyObj);
      boolean res;
      try {
          //调用onTransact函数,派生类可以重新实现这个函数,以完成业务功能
          res = onTransact(code, data, reply, flags);
      }......
      reply.recycle();
      data.recycle();
      return res;
  }
}
ActivityManagerNative类实现了onTransact函数,代码如下:
[-->ActivityManagerNative.java::onTransact]
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
          throws RemoteException {
      switch (code) {
      case START_ACTIVITY_TRANSACTION:
      {
          data.enforceInterface(IActivityManager.descriptor);
          IBinder b = data.readStrongBinder();
          ......
         //再由ActivityManagerService实现业务函数startActivity
         int result = startActivity(app, intent, resolvedType,
                  grantedUriPermissions, grantedMode, resultTo, resultWho,
                  requestCode, onlyIfNeeded, debug, profileFile,
                  profileFd, autoStopProfiler);
          reply.writeNoException();
          reply.writeInt(result);
          return true;
}
由此可以看出,JavaBBinder仅是一个传声筒,它本身不实现任何业务函数,其工作是:
当它收到请求时,只是简单地调用它所绑定的Java层Binder对象的execTransact。
该Binder对象的execTransact调用其子类实现的onTransact函数。
子类的onTransact函数将业务又派发给其子类来完成。请读者务必注意其中的多层继承关系。
通过这种方式,来自客户端的请求就能传递到正确的Java层Binder对象了。图2-3展示了AMS响应请求的整个流程。
 


图2-3 AMS响应请求的流程
图2-3中,右上角的大方框表示AMS这个对象,其间的虚线箭头表示调用子类重载的函数
Nacos 注册服务源码涉及的主要类有以下几个: 1. NamingService:命名服务接口,定义了注册、注销、查询服务的方法。 2. NamingServiceImpl:命名服务的实现类,实现了 NamingService 接口。 3. ServerListManager:服务列表管理器,负责管理服务列表。 4. Instance:服务实例对象,包含了服务实例的基本信息。 5. Service:服务对象,包含了服务的基本信息和服务实例列表。 6. ServiceInfo:服务信息对象,包含了所有服务和服务实例的信息。 7. ServerProxy:服务代理类,负责与服务注册中心通信。 下面对这些类进行详细的分析。 1. NamingService 命名服务接口,定义了注册、注销、查询服务的方法。 ```java public interface NamingService { /** * 注册一个服务实例 */ void registerInstance(String serviceName, Instance instance) throws NacosException; /** * 注销一个服务实例 */ void deregisterInstance(String serviceName, Instance instance) throws NacosException; /** * 查询一个服务的所有实例 */ List<Instance> getAllInstances(String serviceName) throws NacosException; /** * 监听一个服务的实例变化 */ void subscribe(String serviceName, EventListener listener) throws NacosException; /** * 取消监听一个服务的实例变化 */ void unsubscribe(String serviceName, EventListener listener) throws NacosException; } ``` 2. NamingServiceImpl 命名服务的实现类,实现了 NamingService 接口。 ```java public class NamingServiceImpl implements NamingService { private ServerProxy serverProxy; public NamingServiceImpl(ServerProxy serverProxy) { this.serverProxy = serverProxy; } @Override public void registerInstance(String serviceName, Instance instance) throws NacosException { serverProxy.registerService(serviceName, instance); } @Override public void deregisterInstance(String serviceName, Instance instance) throws NacosException { serverProxy.deregisterService(serviceName, instance); } @Override public List<Instance> getAllInstances(String serviceName) throws NacosException { return serverProxy.getAllInstances(serviceName); } @Override public void subscribe(String serviceName, EventListener listener) throws NacosException { serverProxy.subscribe(serviceName, listener); } @Override public void unsubscribe(String serviceName, EventListener listener) throws NacosException { serverProxy.unsubscribe(serviceName, listener); } } ``` 3. ServerListManager 服务列表管理器,负责管理服务列表。 ```java public class ServerListManager { private DiscoveryConfig config; private List<ServerInfo> serverList = new ArrayList<>(); private AtomicInteger index = new AtomicInteger(0); public ServerListManager(DiscoveryConfig config) { this.config = config; initServerList(); } private void initServerList() { // 读取配置文件中的服务地址列表 String serverListStr = config.getServerList(); String[] serverArr = serverListStr.split(","); for (int i = 0; i < serverArr.length; i++) { String[] serverInfoArr = serverArr[i].split(":"); String ip = serverInfoArr[0]; int port = Integer.parseInt(serverInfoArr[1]); ServerInfo serverInfo = new ServerInfo(ip, port); serverList.add(serverInfo); } } public ServerInfo getNextServer() { // 轮询获取服务地址 int i = index.getAndIncrement() % serverList.size(); return serverList.get(i); } } ``` 4. Instance 服务实例对象,包含了服务实例的基本信息。 ```java public class Instance { private String serviceName; private String ip; private int port; public Instance(String serviceName, String ip, int port) { this.serviceName = serviceName; this.ip = ip; this.port = port; } public String getServiceName() { return serviceName; } public void setServiceName(String serviceName) { this.serviceName = serviceName; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } } ``` 5. Service 服务对象,包含了服务的基本信息和服务实例列表。 ```java public class Service { private String name; private List<Instance> instances = new ArrayList<>(); public Service(String name) { this.name = name; } public String getName() { return name; } public List<Instance> getInstances() { return instances; } public void addInstance(Instance instance) { instances.add(instance); } public void removeInstance(Instance instance) { instances.remove(instance); } } ``` 6. ServiceInfo 服务信息对象,包含了所有服务和服务实例的信息。 ```java public class ServiceInfo { private Map<String, Service> serviceMap = new HashMap<>(); public void addService(Service service) { serviceMap.put(service.getName(), service); } public void removeService(Service service) { serviceMap.remove(service.getName()); } public List<Service> getServices() { return new ArrayList<>(serviceMap.values()); } } ``` 7. ServerProxy 服务代理类,负责与服务注册中心通信。 ```java public class ServerProxy { private ServerListManager serverListManager; public ServerProxy(ServerListManager serverListManager) { this.serverListManager = serverListManager; } public void registerService(String serviceName, Instance instance) throws NacosException { ServerInfo serverInfo = serverListManager.getNextServer(); try (Socket socket = new Socket(serverInfo.getIp(), serverInfo.getPort())) { // 向注册中心发送注册请求 // ... } catch (IOException e) { // 处理异常 } } public void deregisterService(String serviceName, Instance instance) throws NacosException { // 向注册中心发送注销请求 // ... } public List<Instance> getAllInstances(String serviceName) throws NacosException { // 从注册中心获取服务实例列表 // ... return instances; } public void subscribe(String serviceName, EventListener listener) throws NacosException { // 向注册中心发送订阅请求 // ... } public void unsubscribe(String serviceName, EventListener listener) throws NacosException { // 向注册中心发送取消订阅请求 // ... } } ``` 以上就是 Nacos 注册服务源码分析的内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值