11

Binder: ServiceManager的获取

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzIzNTc5NDY4Nw%3D%3D&%3Bmid=2247485536&%3Bidx=1&%3Bsn=ede4bc6f83ae86e482015f435da1f825
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

MNRNzm3.png!mobile

在Binder纯理论分析中介绍了 Binder 的整个通信流程。

下面我们直接通过 Service 的注册来了解一下 Binder 的具体工作原理。

我们以 MediaService 为例,来看下 service 的注册过程。 MediaService 对应的启动文件在 main_mediaserver.cpp 中的 main 方法。

frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc __unused, char **argv __unused)
{
    signal(SIGPIPE, SIG_IGN);
 
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm(defaultServiceManager());
    ALOGI("ServiceManager: %p", sm.get());
    MediaPlayerService::instantiate();
    ResourceManagerService::instantiate();
    registerExtensions();
    ::android::hardware::configureRpcThreadpool(16, false);
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    ::android::hardware::joinRpcThreadpool();
}

ProcessState

首先创建了 ProcessState ,它使用了 sp 的强引用类型。

ProcessState::self 内部是一个单例,如果为空它会创建 ProcessState 对象

ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver)) // 启动binder驱动
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mWaitingForThreads(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS) // 设置最大线程数
    , mStarvationStartTimeMs(0)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
    , mCallRestriction(CallRestriction::NONE)
{

    if (mDriverFD >= 0) {
        // 映射虚拟内存地址
        mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
            close(mDriverFD);
            mDriverFD = -1;
            mDriverName.clear();
        }
    }

    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened.  Terminating.", driver);
}

上面是 ProcessState 的实例化过程,主要有以下三个重要的设置。

  1. open_driver(driver): 启动 binder 驱动
  2. mMaxThreads(DEFAULT_MAX_BINDER_THREADS): 设置最大线程数16

  3. mmap: 映射虚拟内存地址

static int open_driver(const char *driver)
{
 // 打开binder驱动
    int fd = open(driver, O_RDWR | O_CLOEXEC);
    if (fd >= 0) {
        int vers = 0;
        // 通过ioctl与binder驱动交互,获取binder版本信息
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        if (result == -1) {
            ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
            close(fd);
            fd = -1;
        }
        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
          ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
                vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
            close(fd);
            fd = -1;
        }
        // 设置最大线程数
        size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
        if (result == -1) {
            ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
        }
    } else {
        ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
    }
    return fd;
}

open_driver 中通过 open 打开 binder 驱动,在 binder 驱动中对应的方法是 binder_open ,它会创建 binder_proc 对象,并将进程等相关信息保存到 binder_proc 对象中,并返回 fd 文件描述符。

Linux 中通过 ioctl 方法与设备进行交互,获取 binder 的版本信息,同时设置 binder 的最大线程数16。在 binder 驱动中对应的是 binder_ioctl 方法,该方法主要通过 fd 文件描述符、 ioctl 命令与数据类型来传递数据。

ProcessState 创建的过程中,会通过 mmap 方法,在 binder 驱动中对应的是 binder_mmap 方法,将内核中同一块物理内存分别映射到内核的虚拟内存地址空间与用户的虚拟内存地址空间,保证内核空间 buffer 与用户空间 buffer 的同步操作。

以上就是 ProcessState 的主要流程。

下面继续 main 方法中的下一步操作。

BpServiceManager

sp<IServiceManager> sm(defaultServiceManager());

获取 IServiceManager 对象,所以我们进入 defaultServiceManager 方法

 sp<IServiceManager> defaultServiceManager()
  {
      std::call_once(gSmOnce, []() {
          sp<AidlServiceManager> sm = nullptr;
          while (sm == nullptr) {
              // 重要方法,获取ServiceManager
              sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
              if (sm == nullptr) {
                  ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
                  sleep(1);
              }
          }
          gDefaultServiceManager = new ServiceManagerShim(sm);
      });
      return gDefaultServiceManager;
  }

在该方法中我们发现它会通过 interface_cast 来获取 sm ,这里的 AidlServiceManager 本质就是 IServiceManager 。我们先把这个方法放一放,先看下它的参数获取

ProcessState::self()->getContextObject(nullptr)

嗯,又看到了 ProcessState::self() ,前面已经分析了,它就是一个 ProcessState 单例,所以直接看 getContextObject 方法

 
  sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
  {
      sp<IBinder> context = getStrongProxyForHandle(0);
      if (context == nullptr) {
         ALOGW("Not able to get context object on %s.", mDriverName.c_str());
      }
      internal::Stability::tryMarkCompilationUnit(context.get());
      return context;
  }

返回了 IBinder ,这是我们第一次看到 IBinder ,感觉有点眉目了,继续看 getStrongProxyForHandle(0) ,注意它这里传了一个参数 0

 sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
  {
      sp<IBinder> result;
      AutoMutex _l(mLock);
      handle_entry* e = lookupHandleLocked(handle);
      if (e != nullptr) {
          IBinder* b = e->binder;
          if (b == nullptr || !e->refs->attemptIncWeak(this)) {
              if (handle == 0) {
                  Parcel data;
                  // 数据传输
                  status_t status = IPCThreadState::self()->transact(
                          0, IBinder::PING_TRANSACTION, data, nullptr, 0);
                  if (status == DEAD_OBJECT)
                     return nullptr;
              }
              // 创建BpBinder
              b = BpBinder::create(handle);
              e->binder = b;
              if (b) e->refs = b->getWeakRefs();
              result = b;
          } else {
              result.force_set(b);
              e->refs->decWeak(this);
          }
      }
      return result;
  }

IPCThreadState::self() 也是一个单例,通过它的 transact 方法向远端发送数据,关于数据的发送本期不分析,所以我们暂且跳过。

继续,创建了 BpBinder ,并将 handler = 0 传给它,最终通过 result 返回的就是 BpBinder(0) ,此时已经获取到了 IBinder ,作为跨进程通信的载体。

所以我们向上回退,回到最初的地方 interface_cast ,现在已经知道它的参数其实就是 BpBinder(0) ,即 interface_cast(BpBinder(0))

现在就只剩下 interface_cast 了,只要我们解开它就能知道 ServiceManager 是如何创建并获取的。

  template<typename INTERFACE>
  inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
  {
      return INTERFACE::asInterface(obj);
  }

发现它调用了 INTERFACEasInterface 方法,那么 INTERFACE 又是什么呢?

找了一圈发现它居然是一个模板,声明如下

 #define DECLARE_META_INTERFACE(INTERFACE)                               
  public:                                                                 
      static const ::android::String16 descriptor;                        
      static ::android::sp<I##INTERFACE> asInterface(                    
              const ::android::sp<::android::IBinder>& obj);              
      virtual const ::android::String16& getInterfaceDescriptor() const;  
      I##INTERFACE();                                                     
      virtual ~I##INTERFACE();                                           
      static bool setDefaultImpl(std::unique_ptr<I##INTERFACE> impl);    
      static const std::unique_ptr<I##INTERFACE>& getDefaultImpl();      
  private:                                                                
      static std::unique_ptr<I##INTERFACE> default_impl

这里的 INTERFACE 就是 ServiceManager ,在模板声明中看到了我们所要的 asInterface

下面再看模板函数的具体实现

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

 #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)
      const ::android::StaticString16                                     
          I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME));
      const ::android::String16 I##INTERFACE::descriptor(                 
          I##INTERFACE##_descriptor_static_str16);                        
      const ::android::String16&                                          
              I##INTERFACE::getInterfaceDescriptor() const {              
          return I##INTERFACE::descriptor;                                
      }                                                                   
      ::android::sp<I##INTERFACE> I##INTERFACE::asInterface(              
              const ::android::sp<::android::IBinder>& obj)               
      {                                                                   
          ::android::sp<I##INTERFACE> intr;                               
          if (obj != nullptr) {                                           
              intr = static_cast<I##INTERFACE*>(                          
                  obj->queryLocalInterface(                               
                         I##INTERFACE::descriptor).get());               
             if (intr == nullptr) {                                      
                  intr = new Bp##INTERFACE(obj);                         
             }                                                           
          }                                                               
          return intr;                                                    
      }                      
  ...

INTERFACE 替换成 ServiceManager 来看,最终通过 asInterface 返回的是 BpServiceManager 对象,同时它的参数 obj 对应的就是之前的 BpBinder(0)

搞明白这个之后,再回到最初的地方(希望没有晕),对应的就是 defaultServiceManager 方法。

所以每次调用 defaultServiceManager 其实就是返回 BpServiceManager(BpBinder(0)) 对象。

最后我们再来看下 BpServiceManager ,它在 IServiceManager.cpp 就申明的

 class BpServiceManager : public BpInterface<IServiceManager>
  {
  public:
      explicit BpServiceManager(const sp<IBinder>& impl)
          : BpInterface<IServiceManager>(impl)
      {
      } 
   
      virtual sp<IBinder> getService(const String16& name) const
      { ... }
  
      virtual sp<IBinder> checkService( const String16& name) const
      { ... }
  
      virtual status_t addService(const String16& name, const sp<IBinder>& service,
                                  bool allowIsolated, int dumpsysPriority) { ... }
 
   ...
  };

它提供了 addServicegetService 方法,暂时不分析,但可以大胆猜一下,应该是通过 BpServiceManager 的这些方法来注册与获取对应的 Service 。至于它内部又是如何传递到 ServiceManager 我们后续再分析。

回到最初的 main 方法,我们接下来应该就是

MediaPlayerService::instantiate();

void MediaPlayerService::instantiate() {
 defaultServiceManager()->addService(
  String16("media.player"), new MediaPlayerService());
}

再来看 instantiate 就简单许多了,它通过 defaultServiceManager 向其中注册了名称为 media.playerMediaPlayerService 服务。

defaultServiceManager 对应的是 BpServiceManager(BpBinder(0)) ,所以上面我们的猜想是成立的。关于服务的注册、验证与获取都是通过 BpServiceManager 代理完成的,其实内部最终都是通过 BpBinder(0) 来传输的。

好了,为了尽量缩短篇幅,降低阅读疲劳,提升读者体验,这篇文章就分析到这里。

下面来总结一下 MediaService 所做的一部分核心内容

  1. 创建 ProcessState 对象
  2. ProcessState
    binder
    ioctl
    binder
    binder
    mmap
    
  3. IPCThreadState
    transact
    server
    
  4. 创建 BpBinder 对象,获取 IBinder ,作为跨进程通信的载体
  5. 创建 BpServiceManager 对象,作为服务注册、检验与获取的代理

福 利

为了感谢大家大支持,我特意搞了一个粉丝抽奖福利,只需在公众号后台回复【Android补给站,必出精品】关键字,即可获取二维码进行抽奖,小憩提前预祝大家中奖。

扫码二维码

获取更多精彩

壹伴编辑器

N7zqQb2.jpg!mobile

Mr2qQnm.gif!mobile

点个 在看 你最好看


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK