MediaPlayerService的代码位于frameworks/base/media/mediaserver/main_mediaserver.cpp文件中:
只关心下面的5行代码, 下面一一对这个5行代码分析
int main(int argc, char** argv) { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); MediaPlayerService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }
分析sp<ProcessState> proc(ProcessState::self());
ProcessState类的在frameworks/base/include/binder/ProcessState.h中定义:
class ProcessState : public virtual RefBase { public: static sp<ProcessState> self(); void setContextObject(const sp<IBinder>& object); sp<IBinder> getContextObject(const sp<IBinder>& caller); void setContextObject(const sp<IBinder>& object, const String16& name); sp<IBinder> getContextObject(const String16& name,const sp<IBinder>& caller); void startThreadPool(); typedef bool (*context_check_func)(const String16& name,const sp<IBinder>& caller,void* userData); bool isContextManager(void) const; bool becomeContextManager(context_check_func checkFunc, void* userData); sp<IBinder> getStrongProxyForHandle(int32_t handle); wp<IBinder> 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. Vector<handle_entry>mHandleToObject; bool mManagesContexts; context_check_func mBinderContextCheckFunc; void* mBinderContextUserData; KeyedVector<String16, sp<IBinder> > mContexts; String8 mRootDir; bool mThreadPoolStarted; volatile int32_t mThreadPoolSeq; };
sp<ProcessState> proc(ProcessState::self()):是通过ProcessState::self()调用创建一个ProcessState实例。ProcessState::self()是ProcessState类的一个静态成员变量,定义在frameworks/base/libs/binder/ProcessState.cpp文件中:
sp<ProcessState> ProcessState::self() { //gProcess:全局对象指针,如果这个指针已被赋值则返回它 //gProcess在Static.cpp中定义 :sp<ProcessState> 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映射到内存中