Binder机制之Server端—ProcessState::self()


MediaPlayerService的代码位于frameworks/base/media/mediaserver/main_mediaserver.cpp文件中:

只关心下面的5行代码, 下面一一对这个5行代码分析

int main(int argc, char** argv)  
{  
    sp proc(ProcessState::self());  
    sp sm = defaultServiceManager();  
    MediaPlayerService::instantiate();  
    ProcessState::self()->startThreadPool();  
    IPCThreadState::self()->joinThreadPool();  
}  

分析sp proc(ProcessState::self()); 

ProcessState类的在frameworks/base/include/binder/ProcessState.h中定义:

class ProcessState : public virtual RefBase
{
public:
    static  sp    self();
    void   setContextObject(const sp& object);
    sp  getContextObject(const sp& caller);       
    void   setContextObject(const sp& object, const String16& name);
    sp getContextObject(const String16& name,const sp& caller);

    void                startThreadPool();
                        
  typedef bool (*context_check_func)(const String16& name,const sp& caller,void* userData);
        
     bool                isContextManager(void) const;
     bool                becomeContextManager(context_check_func checkFunc, void* userData);

    sp         getStrongProxyForHandle(int32_t handle);
    wp         getWeakProxyForHandle(int32_t handle);
     void                expungeHandle(int32_t handle, IBinder* binder);
     .....
     void                spawnPooledThread(bool isMain);
            
private:
    friend class IPCThreadState;//IPCThreadState是它的友元类,所以IPCThreadState可以调用它的相关函数
    
     ProcessState();
      ~ProcessState();
     ProcessState(const ProcessState& o);
      struct handle_entry {IBinder* binder; RefBase::weakref_type* refs;};
            
      handle_entry*       lookupHandleLocked(int32_t handle);

      int                 mDriverFD;//binder驱动的文件描述符
      void*               mVMStart; //映射的内存指针
            
      mutable Mutex               mLock;  // protects everything below.
            
      VectormHandleToObject;

      bool                mManagesContexts;
      context_check_func  mBinderContextCheckFunc;
      void*               mBinderContextUserData;          
      KeyedVector > mContexts;
      String8             mRootDir;
      bool                mThreadPoolStarted;
      volatile int32_t    mThreadPoolSeq;
};

sp proc(ProcessState::self()):是通过ProcessState::self()调用创建一个ProcessState实例。ProcessState::self()是ProcessState类的一个静态成员变量,定义在frameworks/base/libs/binder/ProcessState.cpp文件中:     

sp ProcessState::self()
{
   //gProcess:全局对象指针,如果这个指针已被赋值则返回它
   //gProcess在Static.cpp中定义 :sp gProcess;
   if (gProcess != NULL) return gProcess;
    
    AutoMutex _l(gProcessMutex);
   
    //否则的话,则构造ProcessState对象,并付给gProcess
    if (gProcess == NULL) gProcess = new ProcessState;
    return gProcess;
}
new ProcessState,则调用它的构造函数,构造函数的简化形式如下:

ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0)
   {
        
      mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
       
   }
}
说明:构造函数主要做一下内容,先对成员变量进行处理,其中最重要的一个就是,打开binder驱动,并对驱动的文件描述符付给mDriverFD.

            然后,通过mmap函数,映射出binder驱动对应的映射内存缓冲区付给mVMStart.

看open_driver函数的实现:

static int open_driver()
{
    int fd = open("/dev/binder", O_RDWR);//打开binder驱动
    if (fd >= 0) 
    {  
        fcntl(fd, F_SETFD, FD_CLOEXEC);//设置文件操作的一些属性
       
        //通过ioctl+BINDER_VERSION命令,获取binder驱动的版本
        int vers;
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        
        //通过ioctl+BINDER_SET_MAX_THREADS命令,告诉binder驱动最大线程数
        size_t maxThreads = 15;
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
        
    } 
    return fd;
}
这个函数做了一下工作:

1、同binder驱动建立链接

2、获得驱动的版本。

3、通知驱动,我最多可同时启动15个线程来处理Client端的请求

我们来看一下ioctl文件操作函数执行BINDER_VERSION和BINDER_SET_MAX_THREADS命令的过程,这个函数调用最终进入到Binder驱动程序的binder_ioctl函数中,我们只关注相关的部分逻辑:

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int ret;
        //每open一个binder驱动,都会有一个专门的binder_proc管理当前进程的信息,包括进程的ID,当前进程由mmap所映射出的buffer信息
        //以及当前进程所允许的最大线程量,binder_proc会加入到系统的全局链表binder_procs中去
	struct binder_proc *proc = filp->private_data;
	
       //打开binder驱动的进程可以存在多线程,因此binder驱动使用binder_thread来管理对应的线程信息,主要包括线程所属的binder_proc
       //当前状态looper以及一个transaction_stack(我的理解是负责着实际进程间通信交互的源头和目的地) 
       struct binder_thread *thread;
	unsigned int size = _IOC_SIZE(cmd);
	void __user *ubuf = (void __user *)arg;
	
	ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
	
	mutex_lock(&binder_lock);
        
        //第一次时,会创建一个binder_thread结构保存线程信息,保存到对应的进程binder_proc->threads红黑树中
        //第二次时,根据proc里的线程信息去到该进程binder_proc->threads红黑树中去查询,如果有则返回这个结构指针
	thread = binder_get_thread(proc);
	
	switch (cmd) {
  
         //获取版本命令
         case BINDER_VERSION:
                //将BINDER_CURRENT_PROTOCOL_VERSION写入到传入的参数arg指向的用户缓冲区中去就返回了
		if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) {
			ret = -EINVAL;
			goto err;
		}
		break;
	 //设置最大线程数命令
	 case BINDER_SET_MAX_THREADS:
                //把该进程的最大线程数写入该进程的binder_proc结构里
		if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
			ret = -EINVAL;
			goto err;
		}
		break;	
	default:
		ret = -EINVAL;
		goto err;
	}
	ret = 0;

	return ret;
}
总结:这句代码按顺序主要做了下面的工作:

1、构建ProcessState全局对象gProcess.

2、打开binder驱动,建立链接。

3、在驱动内部创建该进程的binder_proc、binder_thread结构,保存该进程的进程信息和线程信息。并加入到系统的红黑树。

4、获得驱动的版本信息。

5、把该进程最到可同时启动的线程数告诉驱动,并保存到该进程的binder_proc结构中。

6、把设备文件/dev/binder映射到内存中


你可能感兴趣的:(android)