Android binder学习笔记2 - 获取ServiceManager

1. 前言

本文主要是binder系列文章的总结笔记,主要是理清binder的总体流程和总体架构,期间会对照Android R进行代码重读,也会按照自己的理解对内容进行调整,以加深对binder总体的理解。本文主要讲述 获取ServiceManager。

2. 主要类与对象

在这里插入图片描述

IInterface:

IServiceManager:

ProcessState:ProcessState是负责打开Binder节点并做mmap映射

IPCThreadState:IPCThreadState是负责与Binder驱动进行具体的命令交互。在android binder设计中,IPCThreadState是一个binder线程的一个抽象,用于管理binder线程的具体执行。这个类被设计为,其对象在每个binder线程中唯一。为了控制这个类的对象的创建,其构造函数也被声明为private,并且只能通过IPCThreadState::self()来创建或访问IPCThreadState类的对象

Bpbinder: 新创建的BpBinder, 会被赋值给binder_entry的binder变量,而binder_entry位于ProcessState类的IPCThreadState友元类中,也就是client端的进程中,IPCThreadState维护者一个binder_entry向量数组,可以保存多个服务的Bpbinder

下面我们主要以vold守护进程这个服务获取serviceManager服务为例说明defaultServiceManager的处理过程

3. vold/main

vold/main
    |--mkdir("/dev/block/vold", 0755);
    |--vm = VolumeManager::Instance()
    |--nm = NetlinkManager::Instance()
    |--vm->start()
    |--process_config(vm, &has_adoptable, &has_quota, &has_reserved)
    |--android::vold::VoldNativeService::start()
    |      |--IPCThreadState::self()->disableBackgroundScheduling(true);
    |      |--BinderService<VoldNativeService>::publish();
    |      |--sp<ProcessState> ps(ProcessState::self())
    |      |--ps->startThreadPool()
    |      |--ps->giveThreadPoolName()
    |--nm->start()
    |--coldboot("/sys/block");
static status_t publish(bool allowIsolated = false,
                            int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
    
    
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
                              dumpFlags);
    }

4. defaultServiceManager

sp<IServiceManager> defaultServiceManager()
    |--sp<AidlServiceManager> sm = nullptr;
    |--sm = interface_cast<AidlServiceManager>
    |             (ProcessState::self()->getContextObject(nullptr));
    |      |--ProcessState::self()
    |      |--sp<IBinder> ProcessState::getContextObject(const sp<IBinder>&)
    |--gDefaultServiceManager = new ServiceManagerShim(sm)
           |--const sp<AidlServiceManager>& impl
           |--mTheRealServiceManager(impl)

gDefaultServiceManager的创建过程,可分解为以下3个步骤:

  1. ProcessState::self():用于获取ProcessState对象(也是单例模式),每个进程有且只有一个ProcessState对象,存在则直接返回,不存在则创建

  2. getContextObject(): 用于获取BpBinder对象,对于handle=0的BpBinder对象,存在则直接返回,不存在才创建

  3. interface_cast():用于获取BpServiceManager对象

sp<IServiceManager> defaultServiceManager()
{
    
    
    std::call_once(gSmOnce, []() {
    
    
        //AidlServiceManager
        sp<AidlServiceManager> sm = nullptr;
        while (sm == nullptr) {
    
    
            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;
}

std::call_once 这个是c++11上的一个新特性,用于需要保证某个流程在多线程场景中也只执行一次,需要和std::once_flag配套使用,用来区分不同的流程。

defaultServiceManager被客户端调用时,最主要的就是要拿到service manager的Bpbinder。

|- - ProcessState::self

ProcessState::self()
   |--if (gProcess != nullptr) return gProcess;
   |--gProcess = new ProcessState(kDefaultDriver)
           |--open_driver(driver)
           |      |--status_t result = ioctl(fd, BINDER_VERSION, &vers)
           |      |--size_t maxThreads = DEFAULT_MAX_BINDER_THREADS
           |      |--result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
           |--mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | 
                     MAP_NORESERVE, mDriverFD, 0);

ProcessState的单例模式的惟一性,因此一个进程只打开binder设备一次,其中ProcessState的成员变量mDriverFD记录binder驱动的fd,用于访问binder设备。ProcessState是负责打开Binder节点并做mmap映射,IPCThreadState是负责与Binder驱动进行具体的命令交互。

open_driver()
会打开binder设备,open()方法经过系统调用,进入Binder驱动,然后调用方法binder_open(),该方法会在Binder驱动层创建一个binder_proc对象,此binder_proc对象是vold进程的,再将binder_proc对象赋值给fd->private_data,同时放入全局链表binder_procs
注:servicemanager作为第一个binder_proc被链入binder_procs,详见Android binder学习笔记1 - 启动ServiceManager

mmap
创建ProcessState对象时会执行mmap,调用mmap()进行内存映射,对应于Binder驱动层的binder_mmap()方法,该方法会在Binder驱动层创建Binder_buffer对象,并放入当前binder_proc的proc->buffers链表。

|- -ProcessState::getContextObject

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>&)
    |  //获取handle=0的IBinder
	|--sp<IBinder> context = getStrongProxyForHandle(0);
	|       |  //本地查找handle为0的handle_entry,刚开始肯定没有
	|       |  //因此handler_entry->binder是nullptr
	|       |--handle_entry* e = lookupHandleLocked(0)
	|       |--IBinder* b = e->binder
	|       |--if (b == nullptr || !e->refs->attemptIncWeak(this))
	|       |      if (handle == 0)
	|       |          //通过ping操作测试binder是否准备就绪
	|       |          status_t status = IPCThreadState::self()->transact(
	|       |              		0, IBinder::PING_TRANSACTION, data, nullptr, 0);
	|       |      //当handle值所对应的IBinder不存在或弱引用无效时,则创建BpBinder对象
	|       |      b = BpBinder::create(handle);
	|       |          |--new BpBinder(handle, trackedUid)
	|       |                |  //将handle相对应Binder的弱引用增加1
	|       |                |--IPCThreadState::self()->incWeakHandle(handle, this)
	|       |      e->binder = b;
	|--internal::Stability::tryMarkCompilationUnit(context.get());
	|--return context

getContextObject()用于获取BpBinder对象,对于handle=0的BpBinder对象,存在则直接返回,不存在才创建

  1. lookupHandleLocked:根据handle值来查找对应的handle_entry, handle_entry是一个结构体,里面记录IBinder和weakref_type两个指针。当handle大于mHandleToObject的Vector长度时,则向该Vector中添加(handle+1-N)个handle_entry结构体,然后再返回handle对应位置的handle_entry结构体指针

当handle值所对应的IBinder不存在或弱引用无效时会创建BpBinder,否则直接获取:

  1. IPCThreadState::self()->transact:针对handle==0的特殊情况,通过PING_TRANSACTION来判断是否准备就绪。

  2. BpBinder::create: 创建BpBinder对象,其中会将handle相对应Binder的弱引用增加1. 新创建的BpBinder, 会被赋值给binder_entry的binder变量,而binder_entry位于ProcessState类,也就是client端的进程中

  3. 如果在context manager还未生效前,一个BpBinder的本地引用就已经被创建,那么驱动将无法提供context manager的引用。

  4. 返回创建的Bpbinder

|- - -lookupHandleLocked

lookupHandleLocked(handle)
    |--const size_t N=mHandleToObject.size();
	|  //当handle大于mHandleToObject的长度时,创建handle_entry
 	|--if (N <= (size_t)handle)
	|     handle_entry e;
	|     e.binder = nullptr;
	|     e.refs = nullptr;
	|     //从mHandleToObject的第N个位置开始,插入(handle+1-N)个e到队列中
	|     status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
	|--return &mHandleToObject.editItemAt(handle)

lookupHandleLocked:根据handle值来查找对应的handle_entry, handle_entry是一个结构体,里面记录IBinder和weakref_type两个指针。当handle大于mHandleToObject的Vector长度时,则向该Vector中添加(handle+1-N)个handle_entry结构体,然后再返回handle对应位置的handle_entry结构体指针

struct handle_entry {
    
    
    IBinder* binder;
    RefBase::weakref_type* refs;
};

|- - -IPCThreadState::self()->transact

当查找到handle_entry为空,且当handle为0,则说明是servicemanager还没有创建binder实体,通过ping操作测试binder是否准备就绪

IPCThreadState* IPCThreadState::self()
    |--if (gHaveTLS.load(std::memory_order_acquire)) {
    
    
    |        //当执行完第一次之后,再次运行的时候就已经有IPCThreadState实例,只需要获取就可以使用
	|        const pthread_key_t k = gTLS;
	|        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
	|        if (st) return st;
	|        return new IPCThreadState;
    |   }
    |--pthread_mutex_lock(&gTLSMutex);
    |  //初始的gHaveTLS的值false,所以第一次调用的时候,会执行这里的代码
    |  if (!gHaveTLS.load(std::memory_order_relaxed)) {
    
    
    |    	int key_create_value = pthread_key_create(&gTLS, threadDestructor);
    |    	if (key_create_value != 0) {
    
    
    |        	pthread_mutex_unlock(&gTLSMutex);
    |        	ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
    |                strerror(key_create_value));
    |        	return nullptr;
    |    	}
    |       //随后将gHaveTLS设置为true
    |    	gHaveTLS.store(true, std::memory_order_release);
    |  }
    |  pthread_mutex_unlock(&gTLSMutex);

IPCThreadState负责与binder进行命令交互,通过IPCThreadState::self来获取IPCThreadState单例,如果存在则返回,否则创建

|- -interface_cast

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

这是一个模板函数,可得出,interface_cast() 等价于 AidlServiceManager::asInterface()。

using AidlServiceManager = android::os::IServiceManager;

而AidlServiceManager就是IServiceManager,因此interface_cast转换为如下:

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

接下来,再来说说asInterface()函数的具体功能。根据frameworks/native/libs/binder/include/binder/IInterface.h文件中IMPLEMENT_META_INTERFACE(INTERFACE, NAME) 的宏定义,对于asInterface()函数,最终转换为:

android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj)
{
    
    
       android::sp<IServiceManager> intr;
        if(obj != NULL) {
    
    
           intr = static_cast<IServiceManager *>(
               obj->queryLocalInterface(IServiceManager::descriptor).get());
           if (intr == NULL) {
    
    
               intr = new BpServiceManager(obj); 
            }
        }
       return intr;
}

对于最新版本的Android R是否不会创建BpServiceManager,而是创建了ServiceManagerShim

|- -ServiceManagerShim(sm)

gDefaultServiceManager = new ServiceManagerShim(sm)
   |--const sp<AidlServiceManager>& impl
   |--mTheRealServiceManager(impl)

创建ServiceManagerShim,ServiceManagerShim实际就是之前版本的BpServiceManager,sm为

参考文档

Binder系列4—获取ServiceManager
Binder进程与线程ProcessState以及IPCThreadState

おすすめ

転載: blog.csdn.net/jasonactions/article/details/119736519