Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析

简介:

在上一篇文章中,我们分析了Android系统进程间通信机制Binder中的Server在启动过程使用Service Manager的addService接口把自己添加到Service Manager守护过程中接受管理。在这一篇文章中,我们将深入到Binder驱动程序源代码去分析Client是如何通过Service Manager的getService接口中来获得Server远程接口的。Client只有获得了Server的远程接口之后,才能进一步调用Server提供的服务。

        这里,我们仍然是通过Android系统中自带的多媒体播放器为例子来说明Client是如何通过IServiceManager::getService接口来获得MediaPlayerService这个Server的远程接口的。假设计读者已经阅读过前面三篇文章浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路、浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路和Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析,即假设Service Manager和MediaPlayerService已经启动完毕,Service Manager现在等待Client的请求。

        这里,我们要举例子说明的Client便是MediaPlayer了,它声明和实现在frameworks/base/include/media/mediaplayer.h和frameworks/base/media/libmedia/mediaplayer.cpp文件中。MediaPlayer继承于IMediaDeathNotifier类,这个类声明和实现在frameworks/base/include/media/IMediaDeathNotifier.h和frameworks/base/media/libmedia//IMediaDeathNotifier.cpp文件中,里面有一个静态成员函数getMeidaPlayerService,它通过IServiceManager::getService接口来获得MediaPlayerService的远程接口。

        在介绍IMediaDeathNotifier::getMeidaPlayerService函数之前,我们先了解一下这个函数的目标。看来前面浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路这篇文章的读者知道,我们在获取Service Manager远程接口时,最终是获得了一个BpServiceManager对象的IServiceManager接口。类似地,我们要获得MediaPlayerService的远程接口,实际上就是要获得一个称为BpMediaPlayerService对象的IMediaPlayerService接口。现在,我们就先来看一下BpMediaPlayerService的类图:

 


        从这个类图可以看到,BpMediaPlayerService继承于BpInterface<IMediaPlayerService>类,即BpMediaPlayerService继承了IMediaPlayerService类和BpRefBase类,这两个类又分别继续了RefBase类。BpRefBase类有一个成员变量mRemote,它的类型为IBinder,实际是一个BpBinder对象。BpBinder类使用了IPCThreadState类来与Binder驱动程序进行交互,而IPCThreadState类有一个成员变量mProcess,它的类型为ProcessState,IPCThreadState类借助ProcessState类来打开Binder设备文件/dev/binder,因此,它可以和Binder驱动程序进行交互。

       BpMediaPlayerService的构造函数有一个参数impl,它的类型为const sp<IBinder>&,从上面的描述中,这个实际上就是一个BpBinder对象。这样,要创建一个BpMediaPlayerService对象,首先就要有一个BpBinder对象。再来看BpBinder类的构造函数,它有一个参数handle,类型为int32_t,这个参数的意义就是请求MediaPlayerService这个远程接口的进程对MediaPlayerService这个Binder实体的引用了。因此,获取MediaPlayerService这个远程接口的本质问题就变为从Service Manager中获得MediaPlayerService的一个句柄了。

       现在,我们就来看一下IMediaDeathNotifier::getMeidaPlayerService的实现:

 
 
  1. // establish binder interface to MediaPlayerService  
  2. /*static*/const sp<IMediaPlayerService>&  
  3. IMediaDeathNotifier::getMediaPlayerService()  
  4. {  
  5.     LOGV("getMediaPlayerService");  
  6.     Mutex::Autolock _l(sServiceLock);  
  7.     if (sMediaPlayerService.get() == 0) {  
  8.         sp<IServiceManager> sm = defaultServiceManager();  
  9.         sp<IBinder> binder;  
  10.         do {  
  11.             binder = sm->getService(String16("media.player"));  
  12.             if (binder != 0) {  
  13.                 break;  
  14.              }  
  15.              LOGW("Media player service not published, waiting...");  
  16.              usleep(500000); // 0.5 s  
  17.         } while(true);  
  18.  
  19.         if (sDeathNotifier == NULL) {  
  20.         sDeathNotifier = new DeathNotifier();  
  21.     }  
  22.     binder->linkToDeath(sDeathNotifier);  
  23.     sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);  
  24.     }  
  25.     LOGE_IF(sMediaPlayerService == 0, "no media player service!?");  
  26.     return sMediaPlayerService;  


        函数首先通过defaultServiceManager函数来获得Service Manager的远程接口,实际上就是获得BpServiceManager的IServiceManager接口,具体可以参考浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路一文。总的来说,这里的语句:


 

 
 
  1. sp<IServiceManager> sm = defaultServiceManager(); 

   相当于是:

 

 
 
  1. sp<IServiceManager> sm = new BpServiceManager(new BpBinder(0));  

 这里的0表示Service Manager的远程接口的句柄值是0。

        接下去的while循环是通过sm->getService接口来不断尝试获得名称为“media.player”的Service,即MediaPlayerService。为什么要通过这无穷循环来得MediaPlayerService呢?因为这时候MediaPlayerService可能还没有启动起来,所以这里如果发现取回来的binder接口为NULL,就睡眠0.5秒,然后再尝试获取,这是获取Service接口的标准做法。
        我们来看一下BpServiceManager::getService的实现:


 

 
 
  1. class BpServiceManager : public BpInterface<IServiceManager>  
  2. {  
  3.     ......  
  4.  
  5.     virtual sp<IBinder> getService(const String16& name) const  
  6.     {  
  7.         unsigned n;  
  8.         for (n = 0; n < 5; n++){  
  9.             sp<IBinder> svc = checkService(name);  
  10.             if (svc != NULLreturn svc;  
  11.             LOGI("Waiting for service %s...\n", String8(name).string());  
  12.             sleep(1);  
  13.         }  
  14.         return NULL;  
  15.     }  
  16.  
  17.     virtual sp<IBinder> checkService( const String16& name) const  
  18.     {  
  19.         Parcel data, reply;  
  20.         data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());  
  21.         data.writeString16(name);  
  22.         remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);  
  23.         return reply.readStrongBinder();  
  24.     }  
  25.  
  26.     ......  
  27. }; 

       BpServiceManager::getService通过BpServiceManager::checkService执行操作。

         在BpServiceManager::checkService中,首先是通过Parcel::writeInterfaceToken往data写入一个RPC头,这个我们在Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析一文已经介绍过了,就是写往data里面写入了一个整数和一个字符串“android.os.IServiceManager”, Service Manager来处理CHECK_SERVICE_TRANSACTION请求之前,会先验证一下这个RPC头,看看是否正确。接着再往data写入一个字符串name,这里就是“media.player”了。回忆一下Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析这篇文章,那里已经往Service Manager中注册了一个名字为“media.player”的MediaPlayerService。

        这里的remote()返回的是一个BpBinder,具体可以参考浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路一文,于是,就进行到BpBinder::transact函数了:


 

 
 
  1. status_t BpBinder::transact(  
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.     // Once a binder has died, it will never come back to life.  
  5.     if (mAlive) {  
  6.         status_t status = IPCThreadState::self()->transact(  
  7.             mHandle, code, data, reply, flags);  
  8.         if (status == DEAD_OBJECT) mAlive = 0;  
  9.         return status;  
  10.     }  
  11.  
  12.     return DEAD_OBJECT;  

   这里的mHandle = 0,code = CHECK_SERVICE_TRANSACTION,flags = 0。

        这里再进入到IPCThread::transact函数中:


 

 
 
  1. status_t IPCThreadState::transact(int32_t handle,  
  2.                                   uint32_t code, const Parcel& data,  
  3.                                   Parcel* reply, uint32_t flags)  
  4. {  
  5.     status_t err = data.errorCheck();  
  6.  
  7.     flags |= TF_ACCEPT_FDS;  
  8.  
  9.     IF_LOG_TRANSACTIONS() {  
  10.         TextOutput::Bundle _b(alog);  
  11.         alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand " 
  12.             << handle << " / code " << TypeCode(code) << ": " 
  13.             << indent << data << dedent << endl;  
  14.     }  
  15.       
  16.     if (err == NO_ERROR) {  
  17.         LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),  
  18.             (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");  
  19.         err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);  
  20.     }  
  21.       
  22.     if (err != NO_ERROR) {  
  23.         if (reply) reply->setError(err);  
  24.         return (mLastError = err);  
  25.     }  
  26.       
  27.     if ((flags & TF_ONE_WAY) == 0) {  
  28.         #if 0  
  29.         if (code == 4) { // relayout  
  30.             LOGI(">>>>>> CALLING transaction 4");  
  31.         } else {  
  32.             LOGI(">>>>>> CALLING transaction %d", code);  
  33.         }  
  34.         #endif  
  35.         if (reply) {  
  36.             err = waitForResponse(reply);  
  37.         } else {  
  38.             Parcel fakeReply;  
  39.             err = waitForResponse(&fakeReply);  
  40.         }  
  41.         #if 0  
  42.         if (code == 4) { // relayout  
  43.             LOGI("<<<<<< RETURNING transaction 4");  
  44.         } else {  
  45.             LOGI("<<<<<< RETURNING transaction %d", code);  
  46.         }  
  47.         #endif  
  48.           
  49.         IF_LOG_TRANSACTIONS() {  
  50.             TextOutput::Bundle _b(alog);  
  51.             alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand " 
  52.                 << handle << ": ";  
  53.             if (reply) alog << indent << *reply << dedent << endl;  
  54.             else alog << "(none requested)" << endl;  
  55.         }  
  56.     } else {  
  57.         err = waitForResponse(NULLNULL);  
  58.     }  
  59.       
  60.     return err;  

    首先是调用函数writeTransactionData写入将要传输的数据到IPCThreadState的成员变量mOut中去:


 

 
 
  1. status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,  
  2.     int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)  
  3. {  
  4.     binder_transaction_data tr;  
  5.  
  6.     tr.target.handle = handle;  
  7.     tr.code = code;  
  8.     tr.flags = binderFlags;  
  9.       
  10.     const status_t err = data.errorCheck();  
  11.     if (err == NO_ERROR) {  
  12.         tr.data_size = data.ipcDataSize();  
  13.         tr.data.ptr.buffer = data.ipcData();  
  14.         tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);  
  15.         tr.data.ptr.offsets = data.ipcObjects();  
  16.     } else if (statusBuffer) {  
  17.         tr.flags |= TF_STATUS_CODE;  
  18.         *statusBuffer = err;  
  19.         tr.data_size = sizeof(status_t);  
  20.         tr.data.ptr.buffer = statusBuffer;  
  21.         tr.offsets_size = 0;  
  22.         tr.data.ptr.offsets = NULL;  
  23.     } else {  
  24.         return (mLastError = err);  
  25.     }  
  26.       
  27.     mOut.writeInt32(cmd);  
  28.     mOut.write(&tr, sizeof(tr));  
  29.       
  30.     return NO_ERROR;  

  结构体binder_transaction_data在上一篇文章Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析已经介绍过,这里不再累述,这个结构体是用来描述要传输的参数的内容的。这里着重描述一下将要传输的参数tr里面的内容,handle = 0,code =  CHECK_SERVICE_TRANSACTION,cmd = BC_TRANSACTION,data里面的数据分别为:

 

 
 
  1. writeInt32(IPCThreadState::self()->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);  
  2. writeString16("android.os.IServiceManager");  
  3. writeString16("media.player"); 

       这是在BpServiceManager::checkService函数里面写进去的,其中前两个是RPC头,Service Manager在收到这个请求时会验证这两个参数是否正确,这点前面也提到了。IPCThread->getStrictModePolicy默认返回0,STRICT_MODE_PENALTY_GATHER定义为:


 

 
 
  1. // Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER  
  2. #define STRICT_MODE_PENALTY_GATHER 0x100 

   我们不关心这个参数的含义,这不会影响我们分析下面的源代码,有兴趣的读者可以研究一下。这里要注意的是,要传输的参数不包含有Binder对象,因此tr.offsets_size = 0。要传输的参数最后写入到IPCThreadState的成员变量mOut中,包括cmd和tr两个数据。

       回到IPCThread::transact函数中,由于(flags & TF_ONE_WAY) == 0为true,即这是一个同步请求,并且reply  != NULL,最终调用:


 

 
 
  1. err = waitForResponse(reply); 

  进入到waitForResponse函数中:


 

 
 
  1. status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)  
  2. {  
  3.     int32_t cmd;  
  4.     int32_t err;  
  5.  
  6.     while (1) {  
  7.         if ((err=talkWithDriver()) < NO_ERROR) break;  
  8.         err = mIn.errorCheck();  
  9.         if (err < NO_ERROR) break;  
  10.         if (mIn.dataAvail() == 0) continue;  
  11.           
  12.         cmd = mIn.readInt32();  
  13.           
  14.         IF_LOG_COMMANDS() {  
  15.             alog << "Processing waitForResponse Command: " 
  16.                 << getReturnString(cmd) << endl;  
  17.         }  
  18.  
  19.         switch (cmd) {  
  20.         case BR_TRANSACTION_COMPLETE:  
  21.             if (!reply && !acquireResult) goto finish;  
  22.             break;  
  23.           
  24.         case BR_DEAD_REPLY:  
  25.             err = DEAD_OBJECT;  
  26.             goto finish;  
  27.  
  28.         case BR_FAILED_REPLY:  
  29.             err = FAILED_TRANSACTION;  
  30.             goto finish;  
  31.           
  32.         case BR_ACQUIRE_RESULT:  
  33.             {  
  34.                 LOG_ASSERT(acquireResult != NULL"Unexpected brACQUIRE_RESULT");  
  35.                 const int32_t result = mIn.readInt32();  
  36.                 if (!acquireResult) continue;  
  37.                 *acquireResult = result ? NO_ERROR : INVALID_OPERATION;  
  38.             }  
  39.             goto finish;  
  40.           
  41.         case BR_REPLY:  
  42.             {  
  43.                 binder_transaction_data tr;  
  44.                 err = mIn.read(&tr, sizeof(tr));  
  45.                 LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");  
  46.                 if (err != NO_ERROR) goto finish;  
  47.  
  48.                 if (reply) {  
  49.                     if ((tr.flags & TF_STATUS_CODE) == 0) {  
  50.                         reply->ipcSetDataReference(  
  51.                             reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),  
  52.                             tr.data_size,  
  53.                             reinterpret_cast<const size_t*>(tr.data.ptr.offsets),  
  54.                             tr.offsets_size/sizeof(size_t),  
  55.                             freeBuffer, this);  
  56.                     } else {  
  57.                         err = *static_cast<const status_t*>(tr.data.ptr.buffer);  
  58.                         freeBuffer(NULL,  
  59.                             reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),  
  60.                             tr.data_size,  
  61.                             reinterpret_cast<const size_t*>(tr.data.ptr.offsets),  
  62.                             tr.offsets_size/sizeof(size_t), this);  
  63.                     }  
  64.                 } else {  
  65.                     freeBuffer(NULL,  
  66.                         reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),  
  67.                         tr.data_size,  
  68.                         reinterpret_cast<const size_t*>(tr.data.ptr.offsets),  
  69.                         tr.offsets_size/sizeof(size_t), this);  
  70.                     continue;  
  71.                 }  
  72.             }  
  73.             goto finish;  
  74.  
  75.         default:  
  76.             err = executeCommand(cmd);  
  77.             if (err != NO_ERROR) goto finish;  
  78.             break;  
  79.         }  
  80.     }  
  81.  
  82. finish:  
  83.     if (err != NO_ERROR) {  
  84.         if (acquireResult) *acquireResult = err;  
  85.         if (reply) reply->setError(err);  
  86.         mLastError = err;  
  87.     }  
  88.       
  89.     return err;  

   这个函数通过IPCThreadState::talkWithDriver与驱动程序进行交互:


 

 
 
  1. status_t IPCThreadState::talkWithDriver(bool doReceive)  
  2. {  
  3.     LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened");  
  4.  
  5.     binder_write_read bwr;  
  6.  
  7.     // Is the read buffer empty?  
  8.     const bool needRead = mIn.dataPosition() >= mIn.dataSize();  
  9.  
  10.     // We don't want to write anything if we are still reading  
  11.     // from data left in the input buffer and the caller  
  12.     // has requested to read the next data.  
  13.     const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;  
  14.  
  15.     bwr.write_size = outAvail;  
  16.     bwr.write_buffer = (long unsigned int)mOut.data();  
  17.  
  18.     // This is what we'll read.  
  19.     if (doReceive && needRead) {  
  20.         bwr.read_size = mIn.dataCapacity();  
  21.         bwr.read_buffer = (long unsigned int)mIn.data();  
  22.     } else {  
  23.         bwr.read_size = 0;  
  24.     }  
  25.  
  26.     ......  
  27.  
  28.     // Return immediately if there is nothing to do.  
  29.     if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;  
  30.  
  31.     bwr.write_consumed = 0;  
  32.     bwr.read_consumed = 0;  
  33.     status_t err;  
  34.     do {  
  35.         ......  
  36. #if defined(HAVE_ANDROID_OS)  
  37.         if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)  
  38.             err = NO_ERROR;  
  39.         else 
  40.             err = -errno;  
  41. #else 
  42.         err = INVALID_OPERATION;  
  43. #endif  
  44.         ......  
  45.     } while (err == -EINTR);  
  46.  
  47.     ......  
  48.  
  49.     if (err >= NO_ERROR) {  
  50.         if (bwr.write_consumed > 0) {  
  51.             if (bwr.write_consumed < (ssize_t)mOut.dataSize())  
  52.                 mOut.remove(0, bwr.write_consumed);  
  53.             else 
  54.                 mOut.setDataSize(0);  
  55.         }  
  56.         if (bwr.read_consumed > 0) {  
  57.             mIn.setDataSize(bwr.read_consumed);  
  58.             mIn.setDataPosition(0);  
  59.         }  
  60.  
  61.         ......  
  62.  
  63.         return NO_ERROR;  
  64.     }  
  65.  
  66.     return err;  

这里的needRead为true,因此,bwr.read_size大于0;outAvail也大于0,因此,bwr.write_size也大于0。函数最后通过:

 

 
 
  1. ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) 

    进入到Binder驱动程序的binder_ioctl函数中。注意,这里的mProcess->mDriverFD是在我们前面调用defaultServiceManager函数获得Service Manager远程接口时,打开的设备文件/dev/binder的文件描述符,mProcess是IPCSThreadState的成员变量。

        Binder驱动程序的binder_ioctl函数中,我们只关注BINDER_WRITE_READ命令相关的逻辑:

 

 
 
  1. static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  
  2. {  
  3.     int ret;  
  4.     struct binder_proc *proc = filp->private_data;  
  5.     struct binder_thread *thread;  
  6.     unsigned int size = _IOC_SIZE(cmd);  
  7.     void __user *ubuf = (void __user *)arg;  
  8.  
  9.     /*printk(KERN_INFO "binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/  
  10.  
  11.     ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);  
  12.     if (ret)  
  13.         return ret;  
  14.  
  15.     mutex_lock(&binder_lock);  
  16.     thread = binder_get_thread(proc);  
  17.     if (thread == NULL) {  
  18.         ret = -ENOMEM;  
  19.         goto err;  
  20.     }  
  21.  
  22.     switch (cmd) {  
  23.     case BINDER_WRITE_READ: {  
  24.         struct binder_write_read bwr;  
  25.         if (size != sizeof(struct binder_write_read)) {  
  26.             ret = -EINVAL;  
  27.             goto err;  
  28.         }  
  29.         if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {  
  30.             ret = -EFAULT;  
  31.             goto err;  
  32.         }  
  33.         if (binder_debug_mask & BINDER_DEBUG_READ_WRITE)  
  34.             printk(KERN_INFO "binder: %d:%d write %ld at %08lx, read %ld at %08lx\n",  
  35.             proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, bwr.read_size, bwr.read_buffer);  
  36.         if (bwr.write_size > 0) {  
  37.             ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);  
  38.             if (ret < 0) {  
  39.                 bwr.read_consumed = 0;  
  40.                 if (copy_to_user(ubuf, &bwr, sizeof(bwr)))  
  41.                     ret = -EFAULT;  
  42.                 goto err;  
  43.             }  
  44.         }  
  45.         if (bwr.read_size > 0) {  
  46.             ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);  
  47.             if (!list_empty(&proc->todo))  
  48.                 wake_up_interruptible(&proc->wait);  
  49.             if (ret < 0) {  
  50.                 if (copy_to_user(ubuf, &bwr, sizeof(bwr)))  
  51.                     ret = -EFAULT;  
  52.                 goto err;  
  53.             }  
  54.         }  
  55.         if (binder_debug_mask & BINDER_DEBUG_READ_WRITE)  
  56.             printk(KERN_INFO "binder: %d:%d wrote %ld of %ld, read return %ld of %ld\n",  
  57.             proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, bwr.read_consumed, bwr.read_size);  
  58.         if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {  
  59.             ret = -EFAULT;  
  60.             goto err;  
  61.         }  
  62.         break;  
  63.                             }  
  64.     ......  
  65.     default:  
  66.         ret = -EINVAL;  
  67.         goto err;  
  68.     }  
  69.     ret = 0;  
  70. err:  
  71.     ......  
  72.     return ret;  

  这里的filp->private_data的值是在defaultServiceManager函数创建ProcessState对象时,在ProcessState构造函数通过open文件操作函数打开设备文件/dev/binder时设置好的,它表示的是调用open函数打开设备文件/dev/binder的进程上下文信息,这里将它取出来保存在proc本地变量中。

        这里的thread本地变量表示当前线程上下文信息,通过binder_get_thread函数获得。在前面执行ProcessState构造函数时,也会通过ioctl文件操作函数进入到这个函数,那是第一次进入到binder_ioctl这里,因此,调用binder_get_thread时,表示当前进程上下文信息的proc变量还没有关于当前线程的上下文信息,因此,会为proc创建一个表示当前线程上下文信息的thread,会保存在proc->threads表示的红黑树结构中。这里调用binder_get_thread就可以直接从proc找到并返回了。

        进入到BINDER_WRITE_READ相关的逻辑。先看看BINDER_WRITE_READ的定义:


 

 
 
  1. #define BINDER_WRITE_READ           _IOWR('b', 1, struct binder_write_read) 

     这里可以看出,BINDER_WRITE_READ命令的参数类型为struct binder_write_read:


 

 
 
  1. struct binder_write_read {  
  2.     signed long write_size; /* bytes to write */  
  3.     signed long write_consumed; /* bytes consumed by driver */  
  4.     unsigned long   write_buffer;  
  5.     signed long read_size;  /* bytes to read */  
  6.     signed long read_consumed;  /* bytes consumed by driver */  
  7.     unsigned long   read_buffer;  
  8. }; 

  这个结构体的含义可以参考浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路一文。这里首先是通过copy_from_user函数把用户传进来的参数的内容拷贝到本地变量bwr中。
        从上面的调用过程,我们知道,这里bwr.write_size是大于0的,因此进入到binder_thread_write函数中,我们只关注BC_TRANSACTION相关的逻辑:


 

 
 
  1. int 
  2. binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,  
  3.                     void __user *buffer, int size, signed long *consumed)  
  4. {  
  5.     uint32_t cmd;  
  6.     void __user *ptr = buffer + *consumed;  
  7.     void __user *end = buffer + size;  
  8.  
  9.     while (ptr < end && thread->return_error == BR_OK) {  
  10.         if (get_user(cmd, (uint32_t __user *)ptr))  
  11.             return -EFAULT;  
  12.         ptr += sizeof(uint32_t);  
  13.         if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {  
  14.             binder_stats.bc[_IOC_NR(cmd)]++;  
  15.             proc->stats.bc[_IOC_NR(cmd)]++;  
  16.             thread->stats.bc[_IOC_NR(cmd)]++;  
  17.         }  
  18.         switch (cmd) {  
  19.         ......  
  20.         case BC_TRANSACTION:  
  21.         case BC_REPLY: {  
  22.             struct binder_transaction_data tr;  
  23.  
  24.             if (copy_from_user(&tr, ptr, sizeof(tr)))  
  25.                 return -EFAULT;  
  26.             ptr += sizeof(tr);  
  27.             binder_transaction(proc, thread, &tr, cmd == BC_REPLY);  
  28.             break;  
  29.                        }  
  30.         ......  
  31.         default:  
  32.             printk(KERN_ERR "binder: %d:%d unknown command %d\n", proc->pid, thread->pid, cmd);  
  33.             return -EINVAL;  
  34.         }  
  35.         *consumed = ptr - buffer;  
  36.     }  
  37.     return 0;  

  这里再次把用户传出来的参数拷贝到本地变量tr中,tr的类型为struct binder_transaction_data,这个就是前面我们在IPCThreadState::writeTransactionData写入的内容了。

        接着进入到binder_transaction函数中,不相关的代码我们忽略掉:


 

 
 
  1. static void  
  2. binder_transaction(struct binder_proc *proc, struct binder_thread *thread,  
  3. struct binder_transaction_data *tr, int reply)  
  4. {  
  5.     struct binder_transaction *t;  
  6.     struct binder_work *tcomplete;  
  7.     size_t *offp, *off_end;  
  8.     struct binder_proc *target_proc;  
  9.     struct binder_thread *target_thread = NULL;  
  10.     struct binder_node *target_node = NULL;  
  11.     struct list_head *target_list;  
  12.     wait_queue_head_t *target_wait;  
  13.     struct binder_transaction *in_reply_to = NULL;  
  14.     struct binder_transaction_log_entry *e;  
  15.     uint32_t return_error;  
  16.  
  17.     .......  
  18.  
  19.     if (reply) {  
  20.         ......  
  21.     } else {  
  22.         if (tr->target.handle) {  
  23.             ......  
  24.         } else {  
  25.             target_node = binder_context_mgr_node;  
  26.             if (target_node == NULL) {  
  27.                 return_error = BR_DEAD_REPLY;  
  28.                 goto err_no_context_mgr_node;  
  29.             }  
  30.         }  
  31.         ......  
  32.         target_proc = target_node->proc;  
  33.         if (target_proc == NULL) {  
  34.             return_error = BR_DEAD_REPLY;  
  35.             goto err_dead_binder;  
  36.         }  
  37.         if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {  
  38.             ......  
  39.         }  
  40.     }  
  41.     if (target_thread) {  
  42.         ......  
  43.     } else {  
  44.         target_list = &target_proc->todo;  
  45.         target_wait = &target_proc->wait;  
  46.     }  
  47.     ......  
  48.  
  49.     /* TODO: reuse incoming transaction for reply */  
  50.     t = kzalloc(sizeof(*t), GFP_KERNEL);  
  51.     if (t == NULL) {  
  52.         return_error = BR_FAILED_REPLY;  
  53.         goto err_alloc_t_failed;  
  54.     }  
  55.     binder_stats.obj_created[BINDER_STAT_TRANSACTION]++;  
  56.  
  57.     tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);  
  58.     if (tcomplete == NULL) {  
  59.         return_error = BR_FAILED_REPLY;  
  60.         goto err_alloc_tcomplete_failed;  
  61.     }  
  62.     binder_stats.obj_created[BINDER_STAT_TRANSACTION_COMPLETE]++;  
  63.  
  64.     t->debug_id = ++binder_last_id;  
  65.       
  66.     ......  
  67.  
  68.  
  69.     if (!reply && !(tr->flags & TF_ONE_WAY))  
  70.         t->from = thread;  
  71.     else 
  72.         t->from = NULL;  
  73.     t->sender_euid = proc->tsk->cred->euid;  
  74.     t->to_proc = target_proc;  
  75.     t->to_thread = target_thread;  
  76.     t->code = tr->code;  
  77.     t->flags = tr->flags;  
  78.     t->priority = task_nice(current);  
  79.     t->buffer = binder_alloc_buf(target_proc, tr->data_size,  
  80.         tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));  
  81.     if (t->buffer == NULL) {  
  82.         return_error = BR_FAILED_REPLY;  
  83.         goto err_binder_alloc_buf_failed;  
  84.     }  
  85.     t->buffer->allow_user_free = 0;  
  86.     t->buffer->debug_id = t->debug_id;  
  87.     t->buffer->transaction = t;  
  88.     t->buffer->target_node = target_node;  
  89.     if (target_node)  
  90.         binder_inc_node(target_node, 1, 0, NULL);  
  91.  
  92.     offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));  
  93.  
  94.     if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {  
  95.         ......  
  96.         return_error = BR_FAILED_REPLY;  
  97.         goto err_copy_data_failed;  
  98.     }  
  99.  
  100.     ......  
  101.  
  102.     if (reply) {  
  103.         ......  
  104.     } else if (!(t->flags & TF_ONE_WAY)) {  
  105.         BUG_ON(t->buffer->async_transaction != 0);  
  106.         t->need_reply = 1;  
  107.         t->from_parent = thread->transaction_stack;  
  108.         thread->transaction_stack = t;  
  109.     } else {  
  110.         ......  
  111.     }  
  112.  
  113.     t->work.type = BINDER_WORK_TRANSACTION;  
  114.     list_add_tail(&t->work.entry, target_list);  
  115.     tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;  
  116.     list_add_tail(&tcomplete->entry, &thread->todo);  
  117.     if (target_wait)  
  118.         wake_up_interruptible(target_wait);  
  119.     return;  
  120.  
  121.     ......  

  





本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/965284,如需转载请自行联系原作者

目录
相关文章
|
28天前
|
前端开发 编译器 Android开发
构建高效Android应用:探究Kotlin协程的异步处理机制
【4月更文挑战第2天】在现代移动应用开发中,提供流畅且响应迅速的用户体验是至关重要的。随着Android平台的发展,Kotlin语言凭借其简洁性和功能性编程的特点成为了主流选择之一。特别地,Kotlin协程作为一种新型的轻量级线程管理机制,为开发者提供了强大的异步处理能力,从而显著提升了应用程序的性能和响应速度。本文将深入探讨Kotlin协程在Android中的应用,分析其原理、实现以及如何通过协程优化应用性能。
|
8天前
|
安全 Java 定位技术
Android 浅度解析:AIDL & Binder (1)
Android 浅度解析:AIDL & Binder (1)
37 0
|
7天前
|
Android开发
Android源代码定制:Overlay目录定制|调试Overlay资源是否生效
Android源代码定制:Overlay目录定制|调试Overlay资源是否生效
12 0
|
7天前
|
Java Android开发 C++
Android源代码定制:MK文件执行顺序|属性覆盖
Android源代码定制:MK文件执行顺序|属性覆盖
16 2
Android源代码定制:MK文件执行顺序|属性覆盖
|
7天前
|
Android开发 芯片
Android源代码定制:移除无用lunch|新建lunch|自定义customize.mk
Android源代码定制:移除无用lunch|新建lunch|自定义customize.mk
24 3
|
7天前
|
Android开发
Android源代码定制:添加customize.mk文件进行分项目和分客户的定制
Android源代码定制:添加customize.mk文件进行分项目和分客户的定制
3 0
|
28天前
|
API 调度 Android开发
探索Android应用程序的后台运行机制
在移动应用开发中,了解和掌握Android应用程序的后台运行机制至关重要。本文将深入探讨Android平台上应用程序的后台运行原理及其影响因素,包括后台服务、广播接收器、JobScheduler等关键组件,以及如何有效管理后台任务以提升应用性能和用户体验。
16 3
|
3月前
|
SQL 定位技术 Android开发
分享119个Android手机应用源代码总有一个是你想要的
分享119个Android手机应用源代码总有一个是你想要的
95 2
|
3月前
|
Android开发
分享88个Android控件源代码总有一个是你想要的
分享88个Android控件源代码总有一个是你想要的
23 0
|
7天前
|
消息中间件 网络协议 Java
Android 开发中实现数据传递:广播和Handler
Android 开发中实现数据传递:广播和Handler
12 1

相关实验场景

更多