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,如需转载请自行联系原作者

目录
相关文章
|
3天前
|
存储 安全 Android开发
探索Android与iOS的隐私保护机制
在数字化时代,移动设备已成为我们生活的一部分,而隐私安全是用户最为关注的问题之一。本文将深入探讨Android和iOS两大主流操作系统在隐私保护方面的策略和实现方式,分析它们各自的优势和不足,以及如何更好地保护用户的隐私。
|
22天前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
|
26天前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
46 1
|
27天前
|
存储 安全 数据安全/隐私保护
探索安卓与iOS的隐私保护机制####
【10月更文挑战第15天】 本文深入剖析了安卓和iOS两大操作系统在隐私保护方面的策略与技术实现,旨在揭示两者如何通过不同的技术手段来保障用户数据的安全与隐私。文章将逐一探讨各自的隐私控制功能、加密措施以及用户权限管理,为读者提供一个全面而深入的理解。 ####
46 1
|
29天前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
44 2
|
6月前
|
安全 Java 定位技术
Android 浅度解析:AIDL & Binder (1)
Android 浅度解析:AIDL & Binder (1)
214 0
|
4月前
|
缓存 安全 Java
Android深入Binder拦截问题分析
【7月更文挑战第1天】Android Binder 拦截可实现虚拟化、测试、SDK检测、逆向分析及ROM扩展。通过Java层aidl代理,利用IBinder接口规范来拦截通信。拦截步骤包括:替换Binder服务缓存对象,如ActivityManagerService;代理ServiceManager以控制服务获取。此操作需系统权限,可能涉及安全风险和版本差异,非必要时应谨慎。
|
Java API Android开发
Android中Binder在项目中的具体使用详解
Android中Binder在项目中的具体使用详解
191 0
|
Java Android开发 C++
Android中的Binder概述
Android应用的开发离不开四大组件(Activity,Service,BroadcastReceiver,ContentProvider),而这四大组件所涉及的通信底层都是依赖于Binder IPC机制的。例如当进程A中的Activity要向进程B中的Service通信,这便需要依赖于Binder IPC。不仅如此,整个Android系统架构中,大量采用了Binder机制作为IPC方案,当然也存在部分其它的IPC方式,比如Zygote通信便是采用Socket。 概念:Binder是Android中的一种IPC方式,提供远程过程调用(RFC)功能。
|
Java 开发工具 Android开发
Android中的Binder学习笔记
Android中的Binder学习笔记
Android中的Binder学习笔记