IPCThreadState

来源:互联网 发布:淘宝手机充值代理加盟 编辑:程序博客网 时间:2024/04/30 06:56

IPCThreadState的构造函数是private的:

private:
                                IPCThreadState();

因此,IPCThreadState类的对象,就只能通过成员函数self()来生成:

IPCThreadState* IPCThreadState::self()
{
    if (gHaveTLS) 
    {
restart:
        const pthread_key_t k = gTLS;
        
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) 
            return st;
        
        return new IPCThreadState;
    }
    
    if (gShutdown) return NULL;
    
    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) 
    {
        if (pthread_key_create(&gTLS, threadDestructor) != 0)
        {
            pthread_mutex_unlock(&gTLSMutex);
            return NULL;
        }
        gHaveTLS = true;
    }
    
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}


IPCThreadState类的构造函数:

IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
      mMyThreadId(androidGetTid()),
      mStrictModePolicy(0),
      mLastTransactionBinderFlags(0)
{
    pthread_setspecific(gTLS, this);
    clearCaller();
    mIn.setDataCapacity(256);
    mOut.setDataCapacity(256);
}

设置mIn和mOut两个Parcel的Capacity


IPCThreadState类中,有一个重要的函数,也是private的:

private:

status_t            talkWithDriver(bool doReceive=true);


status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    if (mProcess->mDriverFD <= 0) 
    {
        return -EBADF;
    }
    
    binder_write_read bwr;
    
    // Is the read buffer empty?

    // dataPosition() >= dataSize() 表示mIn中的数据已经被全部读取,没有剩余数据,是empty buffer

    const bool needRead = mIn.dataPosition() >= mIn.dataSize();
    
    // We don't want to write anything if we are still reading
    // from data left in the input buffer and the caller
    // has requested to read the next data.

    // 这个地方有点难理解:

    // needRead为true,表示mIn是empty buffer,可以更新其中的内容,因此此时不管是否需要更新mIn中的数据,

    // 都可以将mOut中的数据写入binder driver, needRead为false时,表示mIn中还有剩余数据,此时只有当doReceive

    // 为false时,不需要更新mIn中的数据时,才能将mOut中的数据写入binder driver;

    // doReceive为false时,不需要更新mIn中的数据,此时mIn是不是empty buffer不重要,都可以将mOut中的数据写入

    // binder driver,如果doReceiver为true,需要更新mIn中的数据,此时needRead必须为true;

    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

    bwr.write_size = outAvail;
    bwr.write_buffer = (long unsigned int)mOut.data();


    // This is what we'll read.

    // mIn中的数据需要更新,并且mIn中没有剩余数据时,mIn中的数据才可以更新

    if (doReceive && needRead) 
    {
        // /* bytes to read */
        bwr.read_size = mIn.dataCapacity();
        bwr.read_buffer = (long unsigned int)mIn.data();
    } 
    else 
    {
        bwr.read_size = 0;
        bwr.read_buffer = 0;
    }
    
    // Return immediately if there is nothing to do.
    if ((bwr.write_size == 0) && (bwr.read_size == 0)) 
        return NO_ERROR;


    bwr.write_consumed = 0;
    bwr.read_consumed = 0;
    
    status_t err;
    do 
    {
        IF_LOG_COMMANDS() 
        {
            alog << "About to read/write, write size = " << mOut.dataSize() << endl;
        }
        
#if defined(HAVE_ANDROID_OS)

        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
#else
        err = INVALID_OPERATION;
#endif

        if (mProcess->mDriverFD <= 0) 
        {
            err = -EBADF;
        }
    }
    while (err == -EINTR);


    if (err >= NO_ERROR)
    {
        if (bwr.write_consumed > 0)
        {
            if (bwr.write_consumed < (ssize_t)mOut.dataSize())
                mOut.remove(0, bwr.write_consumed);
            else
                mOut.setDataSize(0);
        }

        if (bwr.read_consumed > 0)
        {
            mIn.setDataSize(bwr.read_consumed);
            mIn.setDataPosition(0);
        }

        return NO_ERROR;
    }
    
    return err;
}


关于talkWithDriver函数参数doReceive的作用,代码中没有注释,只是缺省其值为true,因此,可以从代码中了解参数doReceive的作用,代码中用到函数talkWithDriver的地方并不多:

查看这几个代码片段,不难发现,当doReceive为true时,talkWithDriver函数后会紧跟对mIn中数据进行处理的代码片段,当doReceive为false时,则后面没有任何对mIn中数据进行处理的代码:

为false时:


为true时:


通过代码,可以确定参数doReceive值的意义:

当doReceive为true时,表示mIn中会收到新的数据,mIn中的数据更新;

当doReceive为false时,表示mIn中不会收到新的数据,mIn中的数据不会更新,函数调用对mIn中现在的数据没有影响;


结构体binder_write_read的定义可以在内核源码文件binder.h中找到:

struct binder_write_read 
{
signed long write_size; /* bytes to write */
signed long write_consumed; /* bytes consumed by driver */
unsigned long write_buffer;
signed long read_size; /* bytes to read */
signed long read_consumed; /* bytes consumed by driver */
unsigned long read_buffer;
};


函数调用 if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)将指向结构体变量bwr的指针传递给binder driver函数:

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

查看binder_ioctl函数的实现代码:

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret;
struct binder_proc *proc = filp->private_data;
struct binder_thread *thread;
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;


/*printk(KERN_INFO "binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/


trace_binder_ioctl(cmd, arg);


ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret)
goto err_unlocked;


binder_lock(__func__);
thread = binder_get_thread(proc);
if (thread == NULL) {
ret = -ENOMEM;
goto err;
}


switch (cmd) {
case BINDER_WRITE_READ: {
struct binder_write_read bwr;
if (size != sizeof(struct binder_write_read)) {
ret = -EINVAL;
goto err;
}

// 将数据从用户空间,复制到内核空间,变量bwr占据的空间
if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
ret = -EFAULT;
goto err;
}
binder_debug(BINDER_DEBUG_READ_WRITE,
    "binder: %d:%d write %ld at %08lx, read %ld at %08lx\n",
    proc->pid, thread->pid, bwr.write_size, bwr.write_buffer,
    bwr.read_size, bwr.read_buffer);


if (bwr.write_size > 0) {
ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
trace_binder_write_done(ret);
if (ret < 0) {
bwr.read_consumed = 0;
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto err;
}
}
if (bwr.read_size > 0) {
ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
trace_binder_read_done(ret);
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait);
if (ret < 0) {
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto err;
}
}
binder_debug(BINDER_DEBUG_READ_WRITE,
    "binder: %d:%d wrote %ld of %ld, read return %ld of %ld\n",
    proc->pid, thread->pid, bwr.write_consumed, bwr.write_size,
    bwr.read_consumed, bwr.read_size);
if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
ret = -EFAULT;
goto err;
}
break;
}
case BINDER_SET_MAX_THREADS:
if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
ret = -EINVAL;
goto err;
}
break;
case BINDER_SET_CONTEXT_MGR:
if (binder_context_mgr_node != NULL) {
printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n");
ret = -EBUSY;
goto err;
}
ret = security_binder_set_context_mgr(proc->tsk);
if (ret < 0)
goto err;
if (binder_context_mgr_uid != -1) {
if (binder_context_mgr_uid != current->cred->euid) {
printk(KERN_ERR "binder: BINDER_SET_"
      "CONTEXT_MGR bad uid %d != %d\n",
      current->cred->euid,
      binder_context_mgr_uid);
ret = -EPERM;
goto err;
}
} else
binder_context_mgr_uid = current->cred->euid;
binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
if (binder_context_mgr_node == NULL) {
ret = -ENOMEM;
goto err;
}
binder_context_mgr_node->local_weak_refs++;
binder_context_mgr_node->local_strong_refs++;
binder_context_mgr_node->has_strong_ref = 1;
binder_context_mgr_node->has_weak_ref = 1;
break;
case BINDER_THREAD_EXIT:
binder_debug(BINDER_DEBUG_THREADS, "binder: %d:%d exit\n",
    proc->pid, thread->pid);
binder_free_thread(proc, thread);
thread = NULL;
break;
case BINDER_VERSION:
if (size != sizeof(struct binder_version)) {
ret = -EINVAL;
goto err;
}
if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) {
ret = -EINVAL;
goto err;
}
break;
default:
ret = -EINVAL;
goto err;
}
ret = 0;
err:
if (thread)
thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
binder_unlock(__func__);
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret && ret != -ERESTARTSYS)
printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
trace_binder_ioctl_done(ret);
return ret;
}

调用binder_thread_write函数和binder_thread_read函数分别执行写入和读取操作;






原创粉丝点击