美文网首页
Binder - 获取ServiceManager服务

Binder - 获取ServiceManager服务

作者: w达不溜w | 来源:发表于2022-03-07 23:39 被阅读0次

    当进程注册服务(addService)和获取服务(getService)时,都需要先调用defaultServiceManager()方法来获取ServiceManager服务

    //资源路径:/frameworks/native/libs/binder/IServiceManager.cpp
    sp<IServiceManager> defaultServiceManager()
    {
      //单例模式,不为空直接返回
      if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
      {
        AutoMutex _l(gDefaultServiceManagerLock);
        //当尝试获取SM时,SM可能为准备就绪,这时通过sleep 1秒后,循环尝试获取直到成功
        while (gDefaultServiceManager == NULL) {
          //SM的创建过程,可以分为3个步骤
          gDefaultServiceManager = interface_cast<IServiceManager>(
            ProcessState::self()->getContextObject(NULL));
          if (gDefaultServiceManager == NULL)
            sleep(1);
        }
      }
      return gDefaultServiceManager;
    }
    

    ①ProcessState::self() 获取ProcessState对象

    1)打开驱动;2)设置线程最大数15;3)mmap,分配大小为1M-8k内存地址空间

    //资源路径:/frameworks/native/libs/binder/ProcessState.cpp
    sp<ProcessState> ProcessState::self()
    {
      //单例模式,不为空直接返回
      if (gProcess != NULL) {
        return gProcess;
      }
      //实例化ProcessState
      gProcess = new ProcessState;
      return gProcess;
    }
    
    #define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
    #define DEFAULT_MAX_BINDER_THREADS 15
    
    ProcessState::ProcessState()
      : mDriverFD(open_driver())
    {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        //通过内存映射,给binder分配一块大小为(1M-8k)的虚拟地址空间,用来接收事务
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
    }
    
    static int open_driver()
    {
      //打开/dev/binder设备,建立与内核的Binder驱动的交互通道
      int fd = open("/dev/binder", O_RDWR);
      //设置最大能支持的线程数为15
      size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
      //通过ioctl设置binder驱动能支持的最大线程数
      result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
    }
    

    ②ProcessState::getContextObject 创建BpBinder对象

    1)创建一个BpBinder(SM的代理对象)

    //资源路径:/frameworks/native/libs/binder/ProcessState.cpp
    sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
    {
      //参数为0,获取SM服务
      return getStrongProxyForHandle(0);
    }
    
    sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
    {
      //查找handle对应的资源项
      handle_entry* e = lookupHandleLocked(handle);
      if (b == NULL || !e->refs->attemptIncWeak(this)) {
        if (handle == 0) {
          //handle为0时,通过PING_TRANSACTION看SM进程是否能访问(ping操作测试binder是否准备就绪)
          status_t status = IPCThreadState::self()->transact(
                            0, IBinder::PING_TRANSACTION, data, NULL, 0);
        }
        //当handle值对应的IBinder不存在或弱引用无效时,创建BpBinder对象
        b = new BpBinder(handle);
      }
    }
    

    ③interface_cast 获取BpServiceManager

    //资源路径:/frameworks/native/include/binder/IInterface.h
    template<typename INTERFACE>
    inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
    {
      //泛型,等价于 IServiceManager::asInterface
      //IServiceManager中找不到asInterface函数,是通过模板函数来定义的
      return INTERFACE::asInterface(obj);
    }
    
    //资源路径:/frameworks/native/include/binder/IServiceManager.h
    IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
    
    //资源路径:/frameworks/native/include/binder/IInterface.h
    //INTERFACE替换成ServiceManager,NAME替换成"android.os.IServiceManager"
    #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       
        const android::String16 I##INTERFACE::descriptor(NAME);             
        const android::String16&                                            
                I##INTERFACE::getInterfaceDescriptor() const {              
            return I##INTERFACE::descriptor;                               
        }                                                                   
        android::sp<I##INTERFACE> I##INTERFACE::asInterface(   
                    //obj是传来的BpBinder
                const android::sp<android::IBinder>& obj)                   
        {                                                                   
            android::sp<I##INTERFACE> intr;                                 
            if (obj != NULL) {                                              
                intr = static_cast<I##INTERFACE*>(                          
                    obj->queryLocalInterface(                               
                            I##INTERFACE::descriptor).get());               
                if (intr == NULL) {     
                    //等价于new BpServiceManager(BpBinder)
                    intr = new Bp##INTERFACE(obj);                          
                }                                                           
            }                                                               
            return intr;                                                    
        }                                                                   
        I##INTERFACE::I##INTERFACE() { }                                    
        I##INTERFACE::~I##INTERFACE() { }
    

    BpServiceManager

    //资源路径:/frameworks/native/libs/binder/IServiceManager.cpp
    class BpServiceManager : public BpInterface<IServiceManager>
    {
      public:
        BpServiceManager(const sp<IBinder>& impl)
            : BpInterface<IServiceManager>(impl)
    }
    
    //资源路径:/frameworks/native/include/binder/IInterface.h
    template<typename INTERFACE>
    inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
        : BpRefBase(remote)
    
    //资源路径:/frameworks/native/libs/binder/Binder.cpp
    //mRemote指向new BpBinder(0),从而BpServiceManager能够利用Binder进行通信
    BpRefBase::BpRefBase(const sp<IBinder>& o)
       : mRemote(o.get()), mRefs(NULL), mState(0)
    

    获取ServiceManager服务 => defaultServiceManager => new BpServiceManager(new BpBinder(0))
    BpServiceManager为客户端代理对象,封装服务要用的接口和方法
    BpBinder为ServiceManager代理对象,具有跨进程的能力

    相关文章

      网友评论

          本文标题:Binder - 获取ServiceManager服务

          本文链接:https://www.haomeiwen.com/subject/hpmorrtx.html