binder总结

数据结构:

//open的时候创建,保存打开设备文件/dev/binder的进程的上下文信息,并且将这个进程上下文信息保存在打开文件结构struct file的私有数据成员变量private_data中
struct binder_proc {
	struct hlist_node proc_node;
	struct rb_root threads;//保存binder_proc进程内用于处理用户请求的线程,它的最大数量由max_threads来决定
	struct rb_root nodes;//保存binder_proc进程内的Binder实体
	struct rb_root refs_by_desc;//以句柄作为key值来保存binder_proc进程内的Binder引用,即引用的其它进程的Binder实体
	struct rb_root refs_by_node;//以引用的实体节点的地址值为key来保存binder_proc进程内的Binder引用,即引用的其它进程的Binder实体
	int pid;
	struct vm_area_struct *vma;
	struct task_struct *tsk;
	struct files_struct *files;
	struct hlist_node deferred_work_node;
	int deferred_work;
	void *buffer;//映射的物理内存在内核空间中的起始位置
	ptrdiff_t user_buffer_offset;//内核使用的虚拟地址与进程使用的虚拟地址之间的差值

	struct list_head buffers;
	struct rb_root free_buffers;
	struct rb_root allocated_buffers;
	size_t free_async_space;

	struct page **pages;//描述具体的物理页面
	size_t buffer_size;//映射的内存的大小
	uint32_t buffer_free;
	struct list_head todo;
	wait_queue_head_t wait;//等待队列
	struct binder_stats stats;
	struct list_head delivered_death;
	int max_threads;//最大线程  
	int requested_threads;
	int requested_threads_started;
	int ready_threads;
	long default_priority;//默认优先级
	struct dentry *debugfs_entry;
};
//管理binder_proc中buffer ~ (buffer + buffer_size)这段地址空间的,这个地址空间被划分为一段一段来管理,每一段是结构体struct binder_buffer来描述
struct binder_buffer {
	struct list_head entry; //按从低址到高地址链入到struct binder_proc中的buffers表示的链表中去
	struct rb_node rb_node; //空闲的链入到struct binder_proc中的free_buffers表示的红黑树中去
							//正在使用的链入到struct binder_proc中的allocated_buffers表示的红黑树中
	unsigned free:1;//空闲标志
	unsigned allow_user_free:1;
	unsigned async_transaction:1;
	unsigned debug_id:29;

	struct binder_transaction *transaction;

	struct binder_node *target_node;//目标节点
	size_t data_size;//表示数据的大小
	size_t offsets_size;//偏移量
	uint8_t data[0];//用于存储实际数据
};
//表示一个线程
struct binder_thread {
	struct binder_proc *proc;//所属进程
	struct rb_node rb_node;//链入binder_proc成员threads这棵红黑树
	int pid;
	int looper;//线程的状态
	struct binder_transaction *transaction_stack;//要接收和发送的进程和线程信息
	struct list_head todo;//发往该线程的数据列表
	uint32_t return_error; //操作结果返回码
	uint32_t return_error2; //操作结果返回码
	wait_queue_head_t wait;
	struct binder_stats stats;
};

//表示一个binder实体
struct binder_node {
	int debug_id;
	struct binder_work work;
	union {
		struct rb_node rb_node;//如果这个Binder实体还在正常使用,则使用rb_node来链入proc->nodes所表示的红黑树的节点
		struct hlist_node dead_node;//如果这个Binder实体所属的进程已经销毁,而这个Binder实体又被其它进程所引用,则这个Binder实体通过dead_node进入到一个哈希表中去存放
	};
	struct binder_proc *proc;//所属进程
	struct hlist_head refs;//引用了该Binder实体的Binder引用连接起来构成一个链表
	int internal_strong_refs;//引用计数
	int local_weak_refs;//引用计数
	int local_strong_refs;//引用计数
	void __user *ptr;//在用户空间的地址
	void __user *cookie;//附加数据
	unsigned has_strong_ref:1;
	unsigned pending_strong_ref:1;
	unsigned has_weak_ref:1;
	unsigned pending_weak_ref:1;
	unsigned has_async_transaction:1;
	unsigned accept_fds:1;
	unsigned min_priority:8;
	struct list_head async_todo;
};

//用户空间通过ioctl读写bind的数据结构
struct binder_write_read {  
    signed long write_size; //写数据大小
    signed long write_consumed; //被消耗的写数据
    unsigned long   write_buffer;  //地址为一个struct binder_transaction_data
    signed long read_size;  //读数据大小
    signed long read_consumed;  //被消耗的读数据
    unsigned long   read_buffer;  //地址为一个struct binder_transaction_data
}; 

struct binder_transaction_data {
	/* The first two are only used for bcTRANSACTION and brTRANSACTION,
	 * identifying the target and contents of the transaction.
	 */
	union {
		size_t	handle;	//处理此事件的目标对象的句柄
		void	*ptr;	//目标对象是本地Binder实体时,就使用ptr来表示这个对象在本进程中的地址
	} target;
	void		*cookie;	//附加数据
	unsigned int	code;	//对目标对象请求的命令代码

	/* General information about the transaction. */
	unsigned int	flags;
	pid_t		sender_pid;//发送者进程的pid
	uid_t		sender_euid;//发送者进程有效用户ID
	size_t		data_size;	//data.buffer缓冲区的大小
	size_t		offsets_size;//data.offsets缓冲区的大小,指定在data.buffer缓冲区中,所有Binder实体或者引用的偏移位置

	/* If this transaction is inline, the data immediately
	 * follows here; otherwise, it ends with a pointer to
	 * the data buffer.
	 */
	union {
		struct {
			/* transaction data */
			const void	*buffer;//真正要传输的数据,分为两类数据:
								// 1、普通数据
								//2、Binder实体或者Binder引用
			/* offsets from buffer to flat_binder_object structs */
			const void	*offsets;
		} ptr;
		uint8_t	buf[8];
	} data;
};

//表示一个Binder实体或者引用
struct flat_binder_object {
	/* 8 bytes for large_flat_header. */
	unsigned long		type;//Binder对象的类型
	unsigned long		flags;//Binder对象的标志

	/* 8 bytes of data. */
	union {
		void		*binder;	//表示这是一个Binder实体
		signed long	handle;		//这是一个Binder引用
	};

	void			*cookie;//附加数据
};

//该结构体主要用来中转请求和返回结果,保存接收和要发送的进程信息
struct binder_transaction {
	int debug_id;//调试相关  
	struct binder_work work;
	struct binder_thread *from;//发送的线程
	struct binder_transaction *from_parent;
	struct binder_proc *to_proc;//接收者进程
	struct binder_thread *to_thread;//接收者线程
	struct binder_transaction *to_parent;
	unsigned need_reply:1;
	/* unsigned is_dead:1; */	/* not used at the moment */

	struct binder_buffer *buffer;//数据地址,在接收者进程中分配
	unsigned int	code;//对目标对象请求的命令代码
	unsigned int	flags;
	long	priority;
	long	saved_priority;
	uid_t	sender_euid;//发送者euid
};

struct binder_work {
	struct list_head entry;//双向链表,存储所有binder_work的队列
	enum {
		BINDER_WORK_TRANSACTION = 1,
		BINDER_WORK_TRANSACTION_COMPLETE,
		BINDER_WORK_NODE,
		BINDER_WORK_DEAD_BINDER,
		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
	} type;
};

enum transaction_flags {
	TF_ONE_WAY	= 0x01,	//单向传递,是异步的,不需要返回
	TF_ROOT_OBJECT	= 0x04,	//组建的根对象,对应类型为本地对象Binder
	TF_STATUS_CODE	= 0x08,	//内容是一个32位的状态码,将对应类型为远程对象的“引用”(即句柄handle)
	TF_ACCEPT_FDS	= 0x10,	//可以接收一个文件描述符,对应的类型为文件(BINDER_TYPE_FD),即handle中存储的为文件描述符
};


//binder引用
struct binder_ref {
	/* Lookups needed: */
	/*   node + proc => ref (transaction) */
	/*   desc + proc => ref (transaction, inc/dec ref) */
	/*   node => refs + procs (proc exit) */
	int debug_id;
	struct rb_node rb_node_desc;//以引用号为索引来将这个binder_ref挂进红黑树中
	struct rb_node rb_node_node;//以binder节点的内存地址为索引来将这个binder_ref挂进红黑树中
	struct hlist_node node_entry;
	struct binder_proc *proc;
	struct binder_node *node;  //内核binder节点的内存地址
	uint32_t desc;
	int strong;
	int weak;
	struct binder_ref_death *death;
};

2、


在上面图中,我们可以看到,在SMGr中拥有各个Service的binder引用及自己的binder实体,各个Service拥有SMGr的binder引用以及自己的binder实体,而client则拥有SMGr和Service的引用。

具体过程:

1、  首先SMGr创建自己的binder实体,成为守护进程,然后等待其线程结构thread->todo上面有事件过来。

2、  Service首先获取SMGr的引用,然后通过这个引用调用它的add Service方法,此时会在该进程的内核空间创建该binder实体,然后把它的引用注册到SMGr

3、  Client首先也是获取SMGr的引用,然后调用getService从SMGr获取这个Service的引用,并在其内核空间创建到这个Service的引用,这样当要调用其方法时就可以直接和这个Service通讯了,这里要注意client中对Service的引用和SMGr中对Service的引用是不一样的,不过指向的bind实体是同一个。

 

这里面之间的数据传递是通过共享内存来进行的,当A需要和B通信时,A进入内核状态后,然后创建一个事件t,然后会查看这个事物t应该交给哪个目标处理,这时就在目标中分配空间并把数据拷贝过去,然后B得到了数据后,映射到相应的用户空间地址,这样在B进程的用户空间就可以访问A传过来的数据了。

(注意这里各个进程的内核空间是在mmap时创建的)

当client获取到了Service的引用后就可以调用Service中的方法了,此时在内核空间会创建一个事物t,并把目标设置为该Service,并有如下设置代码:

 tr.target.ptr = target_node->ptr;
tr.cookie =  target_node->cookie;

这里的 ptr cookie 是在 Service 注册的时候初始化的,我们记得在注册 Service 的时候, Service 调用了 flatten_binder 传进来了一个 IBinder, 这个对角就是这个 Service

status_t flatten_binder(const sp<ProcessState>& proc,
    const sp<IBinder>& binder, Parcel* out)
{
    flat_binder_object obj;
    
    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == NULL) {
                LOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE;
            obj.handle = handle;
            obj.cookie = NULL;
        } else {
            obj.type = BINDER_TYPE_BINDER;
            obj.binder = local->getWeakRefs();
            obj.cookie = local;
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = NULL;
        obj.cookie = NULL;
    }
    
    return finish_flatten_binder(binder, obj, out);
}

这样当Service在内核空间获取到事件返回用户空间的时候,通过如下命令转换成binder用户实体

if (tr.target.ptr) {
                sp<BBinder> b((BBinder*)tr.cookie);
                const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
                if (error < NO_ERROR) reply.setError(error);
}

再调用重写的transact实现相应的功能。

 

3、数据传递过程:

首先在IPCThreadState::writeTransactionData函数中通过如下代码把数据保存到mOut,注意这里的结构是binder_transaction_data

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
    binder_transaction_data tr;

    tr.target.handle = handle;
    tr.code = code;
    tr.flags = binderFlags;
    
    const status_t err = data.errorCheck();
    if (err == NO_ERROR) {
        tr.data_size = data.ipcDataSize();
        tr.data.ptr.buffer = data.ipcData();
        tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);
        tr.data.ptr.offsets = data.ipcObjects();
    } else if (statusBuffer) {
        tr.flags |= TF_STATUS_CODE;
        *statusBuffer = err;
        tr.data_size = sizeof(status_t);
        tr.data.ptr.buffer = statusBuffer;
        tr.offsets_size = 0;
        tr.data.ptr.offsets = NULL;
    } else {
        return (mLastError = err);
    }
    
    mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr));
    
    return NO_ERROR;
}

然后在IPCThreadState::talkWithDriver中

status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened");
    
    binder_write_read bwr;
    
    // Is the read buffer empty?
    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.
    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.
    if (doReceive && needRead) {
        bwr.read_size = mIn.dataCapacity();
        bwr.read_buffer = (long unsigned int)mIn.data();
    } else {
        bwr.read_size = 0;
    }
    
    IF_LOG_COMMANDS() {
        TextOutput::Bundle _b(alog);
        if (outAvail != 0) {
            alog << "Sending commands to driver: " << indent;
            const void* cmds = (const void*)bwr.write_buffer;
            const void* end = ((const uint8_t*)cmds)+bwr.write_size;
            alog << HexDump(cmds, bwr.write_size) << endl;
            while (cmds < end) cmds = printCommand(alog, cmds);
            alog << dedent;
        }
        alog << "Size of receive buffer: " << bwr.read_size
            << ", needRead: " << needRead << ", doReceive: " << doReceive << endl;
    }
    
    // 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_LOG_COMMANDS() {
            alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
        }
    } while (err == -EINTR);
    
   ......
}

首先获取前面保存在mOut中的数据并保存到binder_write_read结构中的write_buffer,再调用ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)把数据传递到内核。

内核中对于BINDER_WRITE_READ,由于write_size大于0,调用ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed)处理,在该函数中,对于BC_TRANSACTION的处理是

		case BC_TRANSACTION:
		case BC_REPLY: {
			struct binder_transaction_data tr;

			if (copy_from_user(&tr, ptr, sizeof(tr)))
				return -EFAULT;
			ptr += sizeof(tr);
			binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
			break;
		}

在binder_transaction中会把相应的数据拷贝到目标进程的内核空间中,相应的代码:

	t->buffer = binder_alloc_buf(target_proc, tr->data_size,
		tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
	if (t->buffer == NULL) {
		return_error = BR_FAILED_REPLY;
		goto err_binder_alloc_buf_failed;
	}
	t->buffer->allow_user_free = 0;
	t->buffer->debug_id = t->debug_id;
	t->buffer->transaction = t;
	t->buffer->target_node = target_node;
	if (target_node)
		binder_inc_node(target_node, 1, 0, NULL);

	offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));

	if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
		binder_user_error("binder: %d:%d got transaction with invalid "
			"data ptr\n", proc->pid, thread->pid);
		return_error = BR_FAILED_REPLY;
		goto err_copy_data_failed;
	}
	if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
		binder_user_error("binder: %d:%d got transaction with invalid "
			"offsets ptr\n", proc->pid, thread->pid);
		return_error = BR_FAILED_REPLY;
		goto err_copy_data_failed;
	}

这样数据就到了目标进程。
目标进程一般睡眠在binder_thread_read函数中的wait_event_interruptible_exclusive上,被唤醒后会把前面请求进程的事务t中的数据拷贝到本地局部变量struct binder_transaction_data tr中,把数据映射到相对应的用户空间地址。

		tr.code = t->code;
		tr.flags = t->flags;
		tr.sender_euid = t->sender_euid;

		if (t->from) {
			struct task_struct *sender = t->from->proc->tsk;
			tr.sender_pid = task_tgid_nr_ns(sender,
							current->nsproxy->pid_ns);
		} else {
			tr.sender_pid = 0;
		}

		tr.data_size = t->buffer->data_size;
		tr.offsets_size = t->buffer->offsets_size;
		tr.data.ptr.buffer = (void *)t->buffer->data +
					proc->user_buffer_offset;
		tr.data.ptr.offsets = tr.data.ptr.buffer +
					ALIGN(t->buffer->data_size,
					    sizeof(void *));

		if (put_user(cmd, (uint32_t __user *)ptr))
			return -EFAULT;
		ptr += sizeof(uint32_t);
		if (copy_to_user(ptr, &tr, sizeof(tr)))
			return -EFAULT;
		ptr += sizeof(tr);

调用put_user把tr的内容拷贝到用户传进来的缓冲区,指针ptr指向这个用户缓冲区的地址,接着后面会回到目标进程的处理函数对数据进行处理,这样主完成了数据 从一个进程传到另一个进程。数据的拷贝也只有一个,即从用户空间到内核空间


4、binder传递

首先在addService中

    virtual status_t addService(const String16& name, const sp<IBinder>& service)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeStrongBinder(service);
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
        return err == NO_ERROR ? reply.readExceptionCode() : err;
    }
这里写入一个binder
data.writeStrongBinder(service);
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}
struct flat_binder_object来表示传输中的一个binder对象,它的定义如下所示:

/*
 * This is the flattened representation of a Binder object for transfer
 * between processes.  The 'offsets' supplied as part of a binder transaction
 * contains offsets into the data where these structures occur.  The Binder
 * driver takes care of re-writing the structure type and data as it moves
 * between processes.
 */
struct flat_binder_object {
	/* 8 bytes for large_flat_header. */
	unsigned long		type;
	unsigned long		flags;

	/* 8 bytes of data. */
	union {
		void		*binder;	/* local object */
		signed long	handle;		/* remote object */
	};

	/* extra data associated with local object */
	void			*cookie;
};

看下flatten_binder

status_t flatten_binder(const sp<ProcessState>& proc,
    const sp<IBinder>& binder, Parcel* out)
{
    flat_binder_object obj;
    
    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == NULL) {
                LOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE;
            obj.handle = handle;
            obj.cookie = NULL;
        } else {
            obj.type = BINDER_TYPE_BINDER;
            obj.binder = local->getWeakRefs();
            obj.cookie = local;
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = NULL;
        obj.cookie = NULL;
    }
    
    return finish_flatten_binder(binder, obj, out);
}

传进来的bind一般是继承自BBinder的本地Binder实体,因此binder->localBinder返回一个BBinder指针,而且肯定不为空,于是执行下面语句:

obj.type = BINDER_TYPE_BINDER;
obj.binder = local->getWeakRefs();
obj.cookie = local;

函数最后调用finish_flatten_binder来将这个flat_binder_obj写入到Parcel中去:
status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData)
{
    const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity;
    const bool enoughObjects = mObjectsSize < mObjectsCapacity;
    if (enoughData && enoughObjects) {
restart_write:
        *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;
        
        // Need to write meta-data?
        if (nullMetaData || val.binder != NULL) {
            mObjects[mObjectsSize] = mDataPos;
            acquire_object(ProcessState::self(), val, this);
            mObjectsSize++;
        }
        
        // remember if it's a file descriptor
        if (val.type == BINDER_TYPE_FD) {
            mHasFds = mFdsKnown = true;
        }

        return finishWrite(sizeof(flat_binder_object));
    }

    if (!enoughData) {
        const status_t err = growData(sizeof(val));
        if (err != NO_ERROR) return err;
    }
    if (!enoughObjects) {
        size_t newSize = ((mObjectsSize+2)*3)/2;
        size_t* objects = (size_t*)realloc(mObjects, newSize*sizeof(size_t));
        if (objects == NULL) return NO_MEMORY;
        mObjects = objects;
        mObjectsCapacity = newSize;
    }
    
    goto restart_write;
}
*reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;
这里将相关数据写进去, 这里保存了obj的偏移

 mObjects[mObjectsSize] = mDataPos;

 这里因为,如果进程间传输的数据间带有Binder对象的时候,Binder驱动程序需要作进一步的处理,以维护各个Binder实体的一致性

接着调用writeTransactionData将数据写到mOut

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
    binder_transaction_data tr;

    tr.target.handle = handle;
    tr.code = code;
    tr.flags = binderFlags;
    
    const status_t err = data.errorCheck();
    if (err == NO_ERROR) {
        tr.data_size = data.ipcDataSize();
        tr.data.ptr.buffer = data.ipcData();
        tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);
        tr.data.ptr.offsets = data.ipcObjects();
    } else if (statusBuffer) {
        tr.flags |= TF_STATUS_CODE;
        *statusBuffer = err;
        tr.data_size = sizeof(status_t);
        tr.data.ptr.buffer = statusBuffer;
        tr.offsets_size = 0;
        tr.data.ptr.offsets = NULL;
    } else {
        return (mLastError = err);
    }
    
    mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr));
    
    return NO_ERROR;
}

这里调用的是

tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);
tr.data.ptr.offsets = data.ipcObjects();

这里

 tr.data_size就是写入的数据大小

tr.data.ptr.buffer写入的是数据的起始指针

tr.offsets_size写入的是binde的总大小,个数*单个大小

tr.data.ptr.offsets写入的binder的起始地址


数据传到内核后,在binder_transaction处理了这个binder实体

    switch (fp->type) {
    case BINDER_TYPE_BINDER:
    case BINDER_TYPE_WEAK_BINDER: {
	struct binder_ref *ref;
	struct binder_node *node = binder_get_node(proc, fp->binder);
	if (node == NULL) {
		node = binder_new_node(proc, fp->binder, fp->cookie);
		if (node == NULL) {
			return_error = BR_FAILED_REPLY;
			goto err_binder_new_node_failed;
		}
		node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
		node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
	}
	if (fp->cookie != node->cookie) {
		......
		goto err_binder_get_ref_for_node_failed;
	}
	ref = binder_get_ref_for_node(target_proc, node);
	if (ref == NULL) {
		return_error = BR_FAILED_REPLY;
		goto err_binder_get_ref_for_node_failed;
	}
	if (fp->type == BINDER_TYPE_BINDER)
		fp->type = BINDER_TYPE_HANDLE;
	else
		fp->type = BINDER_TYPE_WEAK_HANDLE;
	fp->handle = ref->desc;
	binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE, &thread->todo);
	......
							  
	} break;

这里的类型为BINDER_TYPE_BINDER,一般在add services的时候 ,一般是第一次在Binder驱动程序中传输这个services,先获取binder实体,调用binder_get_node函数查询这个Binder实体时,会返回空,于是binder_new_node在proc中新建一个binder_node实体。由于要把这个binder实体交给其它targer(Service Manage)来管理 ,这里建立一个引用,注意下面两句
			if (fp->type == BINDER_TYPE_BINDER)
				fp->type = BINDER_TYPE_HANDLE;
			else
				fp->type = BINDER_TYPE_WEAK_HANDLE;
			fp->handle = ref->desc;

把type这里设置为HANDLE,因为这个binder要在target中处理,而在target中只能够通过句柄值来引用这个Binder实体,所以后面把fp->handle设为引用值。
这样当target进程被唤醒后,就进入处理,这里add service一般是service_manage
会进入如下流程
int svcmgr_handler(struct binder_state *bs,
				   struct binder_txn *txn,
				   struct binder_io *msg,
				   struct binder_io *reply)
{
	struct svcinfo *si;
	uint16_t *s;
	unsigned len;
	void *ptr;
	uint32_t strict_policy;

	if (txn->target != svcmgr_handle)
		return -1;

	// Equivalent to Parcel::enforceInterface(), reading the RPC
	// header with the strict mode policy mask and the interface name.
	// Note that we ignore the strict_policy and don't propagate it
	// further (since we do no outbound RPCs anyway).
	strict_policy = bio_get_uint32(msg);
	s = bio_get_string16(msg, &len);
	if ((len != (sizeof(svcmgr_id) / 2)) ||
		memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
			fprintf(stderr,"invalid id %s\n", str8(s));
			return -1;
	}

	switch(txn->code) {
	......
	case SVC_MGR_ADD_SERVICE:
		s = bio_get_string16(msg, &len);
		ptr = bio_get_ref(msg);
		if (do_add_service(bs, s, len, ptr, txn->sender_euid))
			return -1;
		break;
	......
	}

	bio_put_uint32(reply, 0);
	return 0;
}

这里

strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
s = bio_get_string16(msg, &len);
ptr = bio_get_ref(msg);

依次把前面写入的值读出来。_bio_get_obj这个函数就是从binder_io中取得第一个还没取获取过的binder_object,接着调用do_add_service把service的name和句柄值保存起来。

下面就可以等待客户端来获取services了

客户端首先获取services,调用getService,里面调用了checkService,把servcie的名字写进去,通过binder驱动,把参数写到了service manager进程中,并唤醒它,唤醒之后 ,在用户空间调用do_find_service找到之前我们添加进去的services,然后会把这个service在manager中的句柄值写到驱动,在binder_transaction函数中,会重新New一个这个service的引用,这个引用是在请求service的client端的引用,不同于manager中的引用。并把这个引用返回给client.

在client的用户空间,通过reply.readStrongBinder函数的实现来获取一个binder

sp<IBinder> Parcel::readStrongBinder() const
{
    sp<IBinder> val;
    unflatten_binder(ProcessState::self(), *this, &val);
    return val;
}
这里调用了unflatten_binder函数来构造一个Binder对象:

status_t unflatten_binder(const sp<ProcessState>& proc,
    const Parcel& in, sp<IBinder>* out)
{
    const flat_binder_object* flat = in.readObject(false);
    
    if (flat) {
        switch (flat->type) {
            case BINDER_TYPE_BINDER:
                *out = static_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE:
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->get()), *flat, in);
        }        
    }
    return BAD_TYPE;
}
这里的flat->type是BINDER_TYPE_HANDLE,因此调用ProcessState::getStrongProxyForHandle函数:

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);

    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        // We need to create a new BpBinder if there isn't currently one, OR we
        // are unable to acquire a weak reference on this current one.  See comment
        // in getWeakProxyForHandle() for more info about this.
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            // This little bit of nastyness is to allow us to add a primary
            // reference to the remote proxy when this team doesn't have one
            // but another team is sending the handle to us.
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}
   这里我们可以看到,ProcessState会把使用过的Binder远程接口(BpBinder)缓存起来,这样下次从Service Manager那里请求得到相同的句柄(Handle)时就可以直接返回这个Binder远程接口了,不用再创建一个出来。这里是第一次使用,因此,e->binder为空,于是创建了一个BpBinder对象:
b = new BpBinder(handle); 
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
这样,就获取到了一个binder ,以后就可以通过这个binder与service通信了。

5、相关结构图:




剩下的几点:

1、binder_buffer的分配

2、什么时候把事务放到全局的proc队列,什么时候放入thread队列

3、死亡通知


参考:

http://blog.csdn.net/lizhiguo0532?viewmode=contents

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值