Android Binder ProcessState & IPCThreadState相关介绍

之前几篇博客我们介绍了传统Binder的使用方法,包括c层和java层,这篇博客我们主要介绍下ProcessState和IPCThreadState类的相关方法。


一、正常demon binder调用流程

在一个传统的demon中,如果我们要使用Binder通信,代码大致如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. int main(int argc, char** argv)    
  2.  {    
  3.      sp<ProcessState> proc(ProcessState::self());  
  4.      MediaPlayerService::instantiate();    
  5.      ProcessState::self()->startThreadPool();    
  6.      IPCThreadState::self()->joinThreadPool();    
  7.  }    


1.1 ProcessState::self函数

上面先调用了ProcessState的self方法,

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. sp<ProcessState> ProcessState::self()  
  2. {  
  3.     Mutex::Autolock _l(gProcessMutex);  
  4.     if (gProcess != NULL) {  
  5.         return gProcess;  
  6.     }  
  7.     gProcess = new ProcessState;  
  8.     return gProcess;  
  9. }  

典型的单例模式,我们先来看看ProcessState的构造函数

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. ProcessState::ProcessState()  
  2.     : mDriverFD(open_driver())  
  3.     , mVMStart(MAP_FAILED)  
  4.     , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)  
  5.     , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)  
  6.     , mExecutingThreadsCount(0)  
  7.     , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)  
  8.     , mManagesContexts(false)  
  9.     , mBinderContextCheckFunc(NULL)  
  10.     , mBinderContextUserData(NULL)  
  11.     , mThreadPoolStarted(false)  
  12.     , mThreadPoolSeq(1)  
  13. {  
  14.     if (mDriverFD >= 0) {  
  15.         // XXX Ideally, there should be a specific define for whether we  
  16.         // have mmap (or whether we could possibly have the kernel module  
  17.         // availabla).  
  18. #if !defined(HAVE_WIN32_IPC)  
  19.         // mmap the binder, providing a chunk of virtual address space to receive transactions.  
  20.         mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);  
  21.         if (mVMStart == MAP_FAILED) {  
  22.             // *sigh*  
  23.             ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");  
  24.             close(mDriverFD);  
  25.             mDriverFD = -1;  
  26.         }  
  27. #else  
  28.         mDriverFD = -1;  
  29. #endif  
  30.     }  
  31.   
  32.     LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");  
  33. }  

我们在赋值的时候有如下函数 mDriverFD(open_driver())

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static int open_driver()  
  2. {  
  3.     int fd = open("/dev/binder", O_RDWR);//打开binder驱动  
  4.     if (fd >= 0) {  
  5.         fcntl(fd, F_SETFD, FD_CLOEXEC);  
  6.         int vers = 0;  
  7.         status_t result = ioctl(fd, BINDER_VERSION, &vers);  
  8.         if (result == -1) {  
  9.             ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));  
  10.             close(fd);  
  11.             fd = -1;  
  12.         }  
  13.         if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {  
  14.             ALOGE("Binder driver protocol does not match user space protocol!");  
  15.             close(fd);  
  16.             fd = -1;  
  17.         }  
  18.         size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;//设置binder线程数,默认15  
  19.         result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);  
  20.         if (result == -1) {  
  21.             ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));  
  22.         }  
  23.     } else {  
  24.         ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));  
  25.     }  
  26.     return fd;  
  27. }  

上面这个函数打开了binder驱动节点,然后设置了binder线程数量。binder驱动打开的fd保存在mDriverFD 中。
具体关闭Binder中线程的问题,可以参考Binder通信过程中的用户空间线程池的管理 这篇博文。

上面函数中还通过mmap来把设备文件/dev/binder映射到内存中。


1.2 instantiate函数

而instantiate函数一般是将service注册到serviceManager中去。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. void MediaPlayerService::instantiate() {    
  2.      defaultServiceManager()->addService(    
  3.              String16("media.player"), new MediaPlayerService());    
  4.  }    


1.3 ProcessState::startThreadPool函数

我们再来看startThreadPool函数

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. void ProcessState::startThreadPool()  
  2. {  
  3.     AutoMutex _l(mLock);  
  4.     if (!mThreadPoolStarted) {  
  5.         mThreadPoolStarted = true;  
  6.         spawnPooledThread(true);  
  7.     }  
  8. }  
而在spawnPooledThread函数中,先建了一个线程PoolThread

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. void ProcessState::spawnPooledThread(bool isMain)  
  2. {  
  3.     if (mThreadPoolStarted) {  
  4.         String8 name = makeBinderThreadName();  
  5.         ALOGV("Spawning new pooled thread, name=%s\n", name.string());  
  6.         sp<Thread> t = new PoolThread(isMain);  
  7.         t->run(name.string());  
  8.     }  
  9. }  
我们看下这个PoolThread线程,最后还是调用了IPCThreadState::self()->joinThreadPool(mIsMain);

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class PoolThread : public Thread  
  2. {  
  3. public:  
  4.     PoolThread(bool isMain)  
  5.         : mIsMain(isMain)  
  6.     {  
  7.     }  
  8.       
  9. protected:  
  10.     virtual bool threadLoop()  
  11.     {  
  12.         IPCThreadState::self()->joinThreadPool(mIsMain);  
  13.         return false;  
  14.     }  
  15.       
  16.     const bool mIsMain;  
  17. };  


我们再来看看IPCThreadState的joinThreadPool函数,先看看其定义,参数默认是true。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. void                joinThreadPool(bool isMain = true);  
也就是在main函数中
     ProcessState::self()->startThreadPool();  
     IPCThreadState::self()->joinThreadPool();

这两个函数都是调用了joinThreadPool函数且参数都是true,只是上面的函数新建了一个thread。


1.4 IPCThreadState::joinThreadPool函数

我们再来看看这个函数 joinThreadPool:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. void IPCThreadState::joinThreadPool(bool isMain)  
  2. {  
  3.     LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());  
  4.   
  5.     mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);  
  6.       
  7.     // This thread may have been spawned by a thread that was in the background  
  8.     // scheduling group, so first we will make sure it is in the foreground  
  9.     // one to avoid performing an initial transaction in the background.  
  10.     set_sched_policy(mMyThreadId, SP_FOREGROUND);  
  11.           
  12.     status_t result;  
  13.     do {  
  14.         processPendingDerefs();  
  15.         // now get the next command to be processed, waiting if necessary  
  16.         result = getAndExecuteCommand();  
  17.   
  18.         if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {  
  19.             ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",  
  20.                   mProcess->mDriverFD, result);  
  21.             abort();  
  22.         }  
  23.           
  24.         // Let this thread exit the thread pool if it is no longer  
  25.         // needed and it is not the main process thread.  
  26.         if(result == TIMED_OUT && !isMain) {  
  27.             break;  
  28.         }  
  29.     } while (result != -ECONNREFUSED && result != -EBADF);  
  30.   
  31.     LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n",  
  32.         (void*)pthread_self(), getpid(), (void*)result);  
  33.       
  34.     mOut.writeInt32(BC_EXIT_LOOPER);  
  35.     talkWithDriver(false);  
  36. }  

这个函数就是一个死循环,不断从驱动获取数据,我们来看getAndExecuteCommand函数:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. status_t IPCThreadState::getAndExecuteCommand()  
  2. {  
  3.     status_t result;  
  4.     int32_t cmd;  
  5.   
  6.     result = talkWithDriver();//获取binder驱动数据  
  7.     if (result >= NO_ERROR) {  
  8.         size_t IN = mIn.dataAvail();  
  9.         if (IN < sizeof(int32_t)) return result;  
  10.         cmd = mIn.readInt32();  
  11.         IF_LOG_COMMANDS() {  
  12.             alog << "Processing top-level Command: "  
  13.                  << getReturnString(cmd) << endl;  
  14.         }  
  15.   
  16.         pthread_mutex_lock(&mProcess->mThreadCountLock);  
  17.         mProcess->mExecutingThreadsCount++;  
  18.         pthread_mutex_unlock(&mProcess->mThreadCountLock);  
  19.   
  20.         result = executeCommand(cmd);  
  21.   
  22.         pthread_mutex_lock(&mProcess->mThreadCountLock);  
  23.         mProcess->mExecutingThreadsCount--;  
  24.         pthread_cond_broadcast(&mProcess->mThreadCountDecrement);  
  25.         pthread_mutex_unlock(&mProcess->mThreadCountLock);  
  26.   
  27.         // After executing the command, ensure that the thread is returned to the  
  28.         // foreground cgroup before rejoining the pool.  The driver takes care of  
  29.         // restoring the priority, but doesn't do anything with cgroups so we  
  30.         // need to take care of that here in userspace.  Note that we do make  
  31.         // sure to go in the foreground after executing a transaction, but  
  32.         // there are other callbacks into user code that could have changed  
  33.         // our group so we want to make absolutely sure it is put back.  
  34.         set_sched_policy(mMyThreadId, SP_FOREGROUND);  
  35.     }  
  36.   
  37.     return result;  
  38. }  
getAndExecuteCommand函数中先调用talkWithDriver就是从binder驱动获取数据,然后调用executeCommand执行命令

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. status_t IPCThreadState::executeCommand(int32_t cmd)  
  2. {  
  3.     BBinder* obj;  
  4.     RefBase::weakref_type* refs;  
  5.     status_t result = NO_ERROR;  
  6.       
  7.     switch ((uint32_t)cmd) {  
  8.     case BR_ERROR:  
  9.         result = mIn.readInt32();  
  10.         break;  
  11.           
  12.     case BR_OK:  
  13.         break;  
  14.           
  15. ......  
  16.       
  17.     case BR_TRANSACTION:  
  18.         {  
  19.             binder_transaction_data tr;  
  20.             result = mIn.read(&tr, sizeof(tr));  
  21.             ALOG_ASSERT(result == NO_ERROR,  
  22.                 "Not enough command data for brTRANSACTION");  
  23.             if (result != NO_ERROR) break;  
  24.               
  25.             Parcel buffer;  
  26.             buffer.ipcSetDataReference(  
  27.                 reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),  
  28.                 tr.data_size,  
  29.                 reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),  
  30.                 tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);  
  31.               
  32.             const pid_t origPid = mCallingPid;  
  33.             const uid_t origUid = mCallingUid;  
  34.             const int32_t origStrictModePolicy = mStrictModePolicy;  
  35.             const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;  
  36.   
  37.             mCallingPid = tr.sender_pid;  
  38.             mCallingUid = tr.sender_euid;  
  39.             mLastTransactionBinderFlags = tr.flags;  
  40.   
  41.             int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);  
  42.             if (gDisableBackgroundScheduling) {  
  43.                 if (curPrio > ANDROID_PRIORITY_NORMAL) {  
  44.                     // We have inherited a reduced priority from the caller, but do not  
  45.                     // want to run in that state in this process.  The driver set our  
  46.                     // priority already (though not our scheduling class), so bounce  
  47.                     // it back to the default before invoking the transaction.  
  48.                     setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);  
  49.                 }  
  50.             } else {  
  51.                 if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {  
  52.                     // We want to use the inherited priority from the caller.  
  53.                     // Ensure this thread is in the background scheduling class,  
  54.                     // since the driver won't modify scheduling classes for us.  
  55.                     // The scheduling group is reset to default by the caller  
  56.                     // once this method returns after the transaction is complete.  
  57.                     set_sched_policy(mMyThreadId, SP_BACKGROUND);  
  58.                 }  
  59.             }  
  60.   
  61.             //ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);  
  62.   
  63.             Parcel reply;  
  64.             status_t error;  
  65.             IF_LOG_TRANSACTIONS() {  
  66.                 TextOutput::Bundle _b(alog);  
  67.                 alog << "BR_TRANSACTION thr " << (void*)pthread_self()  
  68.                     << " / obj " << tr.target.ptr << " / code "  
  69.                     << TypeCode(tr.code) << ": " << indent << buffer  
  70.                     << dedent << endl  
  71.                     << "Data addr = "  
  72.                     << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)  
  73.                     << ", offsets addr="  
  74.                     << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;  
  75.             }  
  76.             if (tr.target.ptr) {  
  77.                 sp<BBinder> b((BBinder*)tr.cookie);  
  78.                 error = b->transact(tr.code, buffer, &reply, tr.flags);//这个最终到service的onTransact函数  
  79.   
  80.             } else {  
  81.                 error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);  
  82.             }  
  83.   
  84.             //ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",  
  85.             //     mCallingPid, origPid, origUid);  
  86.               
  87.             if ((tr.flags & TF_ONE_WAY) == 0) {  
  88.                 LOG_ONEWAY("Sending reply to %d!", mCallingPid);  
  89.                 if (error < NO_ERROR) reply.setError(error);  
  90.                 sendReply(reply, 0);  
  91.             } else {  
  92.                 LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);  
  93.             }  
  94.               
  95.             mCallingPid = origPid;  
  96.             mCallingUid = origUid;  
  97.             mStrictModePolicy = origStrictModePolicy;  
  98.             mLastTransactionBinderFlags = origTransactionBinderFlags;  
  99.   
  100.             IF_LOG_TRANSACTIONS() {  
  101.                 TextOutput::Bundle _b(alog);  
  102.                 alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "  
  103.                     << tr.target.ptr << ": " << indent << reply << dedent << endl;  
  104.             }  
  105.               
  106.         }  
  107.         break;  
  108. ......  
  109. }         

上面就是处理各种命令,最后BR_TRANSACTION命令的时候会调用BBinder的transact,最后调用service中的onTransact函数。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. status_t BBinder::transact(  
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.     data.setDataPosition(0);  
  5.   
  6.     status_t err = NO_ERROR;  
  7.     switch (code) {  
  8.         case PING_TRANSACTION:  
  9.             reply->writeInt32(pingBinder());  
  10.             break;  
  11.         default:  
  12.             err = onTransact(code, data, reply, flags);//调用onTransact函数  
  13.             break;  
  14.     }  
  15.   
  16.     if (reply != NULL) {  
  17.         reply->setDataPosition(0);  
  18.     }  
  19.   
  20.     return err;  
  21. }  



二、不使用Binder线程

还记得在healthd中,我们没有使用Binder线程,我们看看代码是怎么写的。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static void binder_event(uint32_t /*epevents*/) {  
  2.     IPCThreadState::self()->handlePolledCommands();  
  3. }  
  4.   
  5. void healthd_mode_android_init(struct healthd_config* /*config*/) {  
  6.     ProcessState::self()->setThreadPoolMaxThreadCount(0);  
  7.     IPCThreadState::self()->disableBackgroundScheduling(true);  
  8.     IPCThreadState::self()->setupPolling(&gBinderFd);  
  9.   
  10.     if (gBinderFd >= 0) {  
  11.         if (healthd_register_event(gBinderFd, binder_event))  
  12.             KLOG_ERROR(LOG_TAG,  
  13.                        "Register for binder events failed\n");  
  14.     }  
  15.   
  16.     gBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar();  
  17.     gBatteryPropertiesRegistrar->publish();  
  18. }  

具体是调用healthd_mode_android_init函数,在这个函数先调用Binder接口,然后将fd 注册到epoll中去,处理函数就是binder_event函数。


2.1 ProcessState::setThreadPoolMaxThreadCount函数

先来看设置Binder最大线程数的函数:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) {  
  2.     status_t result = NO_ERROR;  
  3.     if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) != -1) {  
  4.         mMaxThreads = maxThreads;  
  5.     } else {  
  6.         result = -errno;  
  7.         ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));  
  8.     }  
  9.     return result;  
  10. }  

最后是通过ioctl设置最大线程数。


2.2 IPCThreadState::disableBackgroundScheduling函数

下面我们再来看disableBackgroundScheduling函数,应该是禁止后台线程的意思

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. void IPCThreadState::disableBackgroundScheduling(bool disable)  
  2. {  
  3.     gDisableBackgroundScheduling = disable;  
  4. }  

我们再来看看在哪里使用了gDisableBackgroundScheduling 这个变量, 还是在executeCommand函数中处理BR_TRANSACTION命令时有下面这段代码

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. case BR_TRANSACTION:  
  2.     {  
  3.         binder_transaction_data tr;  
  4.         result = mIn.read(&tr, sizeof(tr));  
  5.         ALOG_ASSERT(result == NO_ERROR,  
  6.             "Not enough command data for brTRANSACTION");  
  7.         if (result != NO_ERROR) break;  
  8.           
  9.         Parcel buffer;  
  10.         buffer.ipcSetDataReference(  
  11.             reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),  
  12.             tr.data_size,  
  13.             reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),  
  14.             tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);  
  15.           
  16.         const pid_t origPid = mCallingPid;  
  17.         const uid_t origUid = mCallingUid;  
  18.         const int32_t origStrictModePolicy = mStrictModePolicy;  
  19.         const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;  
  20.   
  21.         mCallingPid = tr.sender_pid;  
  22.         mCallingUid = tr.sender_euid;  
  23.         mLastTransactionBinderFlags = tr.flags;  
  24.   
  25.         int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);  
  26.         if (gDisableBackgroundScheduling) {  
  27.             if (curPrio > ANDROID_PRIORITY_NORMAL) {  
  28.                 // We have inherited a reduced priority from the caller, but do not  
  29.                 // want to run in that state in this process.  The driver set our  
  30.                 // priority already (though not our scheduling class), so bounce  
  31.                 // it back to the default before invoking the transaction.  
  32.                 setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);  
  33.             }  
  34.         } else {  
  35.             if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {  
  36.                 // We want to use the inherited priority from the caller.  
  37.                 // Ensure this thread is in the background scheduling class,  
  38.                 // since the driver won't modify scheduling classes for us.  
  39.                 // The scheduling group is reset to default by the caller  
  40.                 // once this method returns after the transaction is complete.  
  41.                 set_sched_policy(mMyThreadId, SP_BACKGROUND);  
  42.             }  
  43.         }  


2.3 IPCThreadState::setupPolling


下面我们再来看看setupPolling函数

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. int IPCThreadState::setupPolling(int* fd)  
  2. {  
  3.     if (mProcess->mDriverFD <= 0) {  
  4.         return -EBADF;  
  5.     }  
  6.   
  7.     mOut.writeInt32(BC_ENTER_LOOPER);  
  8.     *fd = mProcess->mDriverFD;  
  9.     return 0;  
  10. }  

我们看代码这个函数只是获取Binder驱动的fd


2.4 Binder驱动 有数据

然后我们把fd加入主线程的epoll进行监听,当Binder驱动有数据的时候,就会调用binder_event函数

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static void binder_event(uint32_t /*epevents*/) {  
  2.     IPCThreadState::self()->handlePolledCommands();  
  3. }  
我们来看下handlePolledCommands函数:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. status_t IPCThreadState::handlePolledCommands()  
  2. {  
  3.     status_t result;  
  4.   
  5.     do {  
  6.         result = getAndExecuteCommand();  
  7.     } while (mIn.dataPosition() < mIn.dataSize());  
  8.   
  9.     processPendingDerefs();  
  10.     flushCommands();  
  11.     return result;  
  12. }  
getAndExecuteCommand函数之前我们分析过,这里再来看下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. status_t IPCThreadState::getAndExecuteCommand()  
  2. {  
  3.     status_t result;  
  4.     int32_t cmd;  
  5.   
  6.     result = talkWithDriver();//获取binder驱动数据  
  7.     if (result >= NO_ERROR) {  
  8.         size_t IN = mIn.dataAvail();  
  9.         if (IN < sizeof(int32_t)) return result;  
  10.         cmd = mIn.readInt32();  
  11.         IF_LOG_COMMANDS() {  
  12.             alog << "Processing top-level Command: "  
  13.                  << getReturnString(cmd) << endl;  
  14.         }  
  15.   
  16.         pthread_mutex_lock(&mProcess->mThreadCountLock);  
  17.         mProcess->mExecutingThreadsCount++;  
  18.         pthread_mutex_unlock(&mProcess->mThreadCountLock);  
  19.   
  20.         result = executeCommand(cmd);//执行命令  
  21.   
  22.         pthread_mutex_lock(&mProcess->mThreadCountLock);  
  23.         mProcess->mExecutingThreadsCount--;  
  24.         pthread_cond_broadcast(&mProcess->mThreadCountDecrement);  
  25.         pthread_mutex_unlock(&mProcess->mThreadCountLock);  
  26.   
  27.         // After executing the command, ensure that the thread is returned to the  
  28.         // foreground cgroup before rejoining the pool.  The driver takes care of  
  29.         // restoring the priority, but doesn't do anything with cgroups so we  
  30.         // need to take care of that here in userspace.  Note that we do make  
  31.         // sure to go in the foreground after executing a transaction, but  
  32.         // there are other callbacks into user code that could have changed  
  33.         // our group so we want to make absolutely sure it is put back.  
  34.         set_sched_policy(mMyThreadId, SP_FOREGROUND);  
  35.     }  
  36.   
  37.     return result;  
  38. }  

先获取binder驱动数据,然后再执行executeCommand函数,和之前一样执行到BR_TRANSACTION命令会调用BBinder的transact,最终执行到service的onTransact函数中。

当然这些数据的处理都是在healthd的主线程中,是epoll在binder驱动有数据的时候执行的。


2.5 处理完数据后 清理工作

我们继续看handlePolledCommands函数

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. status_t IPCThreadState::handlePolledCommands()  
  2. {  
  3.     status_t result;  
  4.   
  5.     do {  
  6.         result = getAndExecuteCommand();  
  7.     } while (mIn.dataPosition() < mIn.dataSize());  
  8.   
  9.     processPendingDerefs();  
  10.     flushCommands();  
  11.     return result;  
  12. }  

最后做一些清理工作,在flushCommands函数中将和binder驱动的交互关闭。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. void IPCThreadState::flushCommands()  
  2. {  
  3.     if (mProcess->mDriverFD <= 0)  
  4.         return;  
  5.     talkWithDriver(false);  
  6. }  



三、总结

这篇博客我们主要讲了使用binder的demon的binder调用流程,以及不使用binder线程的代码调用方法,举例了healthd中的一个例子。



原始地址: http://blog.csdn.net/kc58236582/article/details/51744398

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值