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は自分のビッドエンティティを作って、デーモンプロセスになります.そして、スレッド構造のthread->todoの上にイベントが来るのを待ちます.
2、  ServiceはまずSMGrの参照を取得し、この引用によってそのadd Service方法を呼び出します.このとき、プロセスのカーネル空間でbinderエンティティを作成し、その参照をSMGrに登録します.
3、  ClientはまずSMGrの引用を取得し、そしてget Serviceを呼び出して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

クッキー
はい、あります
サービス
登録する時初期化しました.登録してください.
サービス
の時、
サービス
呼び出しました
flatenbinder
一つ伝わってきた
IBinder
この対角はこれです.
サービス
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);
}
書き換えたトランジットを呼び出して対応する機能を実現します.
 
3、データ転送プロセス:
まずIPCThreadState:writeTransation Data関数では、下記のコードでデータをmOutに保存します.ここの構造はbinder_であることに注意してください.トランスアクションダタ
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_ブザーは、Octl(mProcess->mDriverFDを呼び出し、BINDERWRITEuREAD、&bwr)データをカーネルに転送します.
カーネルの中ではBINDER(u)に対してWRITE_READは、write_によりsizeが0より大きいので、ret=binder_を呼び出します.スリーロード.write(proc,thread,(void_user*)bwr.writemuffer,bwr.writemusize,&bwr.writemend)処理は、この関数の中でBC(u)に対して処理されます.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
", 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
", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; goto err_copy_data_failed; }
このようにデータは目的のプロセスになります.目標のプロセスは一般的にbinder_で寝ます.スリーロード.read関数のwait_イベントinterruptibleexclusiveでは、起動後に前の要求プロセスのトランザクションtのデータをローカル変数struct binderにコピーします.トランスアクション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、ビッドリレー
まず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;
    }
ここでビットを書き込みます.
data.writeStrongBinder(service);
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}
struct flat_binder_objectは転送中の1つの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;
};
flatenを見てください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);
}
伝わってくるビッドは普通BBinderからのローカルBinderエンティティを継承しているので、binder->local BinderはBBinderポインタを返します.そして、必ず空ではないです.
obj.type = BINDER_TYPE_BINDER;
obj.binder = local->getWeakRefs();
obj.cookie = local;
関数の最後の呼び出しfinish_flatenbinderがこれを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エンティティの整合性を維持するために、さらなる処理を行う必要があるからです.
続いて、writeTransation Dataを呼び出して、データを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書き込みはビッドの合計サイズ、個数*単一サイズです.
tr.data.ptr.offsetsに書き込まれた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を呼び出します.ゲットするnode関数がこのBinderエンティティを調べたら、空に戻ります.new_nodeはprocの中で新しいbinderを作ります.nodeエンティティこのbinderエンティティを他のタリガーに預けて管理するため、ここで引用を作成します.次の二つの点に注意してください.
			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
", 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);
前に書いた値を順に読みなさい.ビオ_ゲットするobjという関数はbinder_からです.ioで一番最初に取得したのはまだ取っていないビッドカーです.object、続いてdouを呼び出します.add_serviceはserviceのnameとハンドルの値を保存します.
以下はクライアントがservicesを取得するのを待つことができます.
クライアントはまずservicesを取得して、getServiceを呼び出して、中はcheck Serviceを呼び出して、servcieの名前を書いて、binderを通じて駆動して、パラメータをservice managerの過程に書いて、それを呼び覚ましてから、ユーザー空間でdouを呼び出します.find_serviceが見つかる前に私たちが追加したservicesは、このserviceのmanagerの中のハンドルの値をドライバに書き込みます.transaction関数では、このserviceの引用を新たにNewします.この引用は、serviceを要求するclient端の引用であり、managerの引用とは異なります.そしてこの引用をclientに返します.
clientのユーザ空間で、reply.readStrongBinder関数の実現によって、binderを取得する.
sp<IBinder> Parcel::readStrongBinder() const
{
    sp<IBinder> val;
    unflatten_binder(ProcessState::self(), *this, &val);
    return val;
}
ここでunflatenを呼び出しました.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は、それでProcesStateを呼び出す:get StrongProxyForHandle関数:
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リモートインターフェースをキャッシュしています.このようにして、次回Service Managerから同じハンドルを要求したら、直接にこの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_ブザーの割り当て
2、いつ事務を全体のプロジェクトの列に置きますか?いつthreadの列に入れますか?
3、死亡のお知らせ
参考:
http://blog.csdn.net/lizhiguo0532?view mode=contensts