注意,這里的參數reply = 0,表示這是一個BC_TRANSACTION命令。
??????? 前面我們提到,傳給驅動程序的handle值為0,即這里的tr->target.handle = 0,表示請求的目標Binder對象是Service Manager,因此有:
?
target_node?=?binder_context_mgr_node; ?target_proc?=?target_node->proc; ?target_list?=?&target_proc->todo; ?target_wait?=?&target_proc->wait;? ???? 其中binder_context_mgr_node是在Service Manager通知Binder驅動程序它是守護過程時創建的。
??????? 接著創建一個待完成事項tcomplete,它的類型為struct binder_work,這是等一會要保存在當前線程的todo隊列去的,表示當前線程有一個待完成的事務。緊跟著創建一個待處理事務t,它的類型為struct binder_transaction,這是等一會要存在到Service Manager的todo隊列去的,表示Service Manager當前有一個事務需要處理。同時,這個待處理事務t也要存放在當前線程的待完成事務transaction_stack列表中去:
?
t->from_parent?=?thread->transaction_stack; ?thread->transaction_stack?=?t;? ? 這樣表明當前線程還有事務要處理。
??????? 繼續往下看,就是分別把tcomplete和t放在當前線程thread和Service Manager進程的todo隊列去了:
?
t->work.type?=?BINDER_WORK_TRANSACTION; ?list_add_tail(&t->work.entry,?target_list); ?tcomplete->type?=?BINDER_WORK_TRANSACTION_COMPLETE; ?list_add_tail(&tcomplete->entry,?&thread->todo);? ????? 最后,Service Manager有事情可做了,就要喚醒它了:
wake_up_interruptible(target_wait);? ?? 前面我們提到,此時Service Manager正在等待Client的請求,也就是Service Manager此時正在進入到Binder驅動程序的binder_thread_read函數中,并且休眠在target->wait上,具體參考淺談Service Manager成為Android進程間通信(IPC)機制Binder守護進程之路一文。
??????? 這里,我們暫時忽略Service Manager被喚醒之后的情景,繼續看當前線程的執行。
??????? 函數binder_transaction執行完成之后,就一路返回到binder_ioctl函數里去了。函數binder_ioctl從binder_thread_write函數調用處返回后,發現bwr.read_size大于0,于是就進入到binder_thread_read函數去了:
?
static?int?binder_thread_read(struct?binder_proc?*proc,?struct?binder_thread?*thread, ????????????????????void??__user?*buffer,?int?size,?signed?long?*consumed,?int?non_block) ?{ ?????void?__user?*ptr?=?buffer?+?*consumed; ?????void?__user?*end?=?buffer?+?size; ??????int?ret?=?0; ?????int?wait_for_proc_work; ??????if?(*consumed?==?0)?{ ?????????if?(put_user(BR_NOOP,?(uint32_t?__user?*)ptr)) ?????????????return?-EFAULT; ?????????ptr?+=?sizeof(uint32_t); ?????} ??retry: ?????wait_for_proc_work?=?thread->transaction_stack?==?NULL?&&?list_empty(&thread->todo); ??????...... ????? ?????if?(wait_for_proc_work)?{ ?????????...... ?????}?else?{ ?????????if?(non_block)?{ ?????????????if?(!binder_has_thread_work(thread)) ?????????????????ret?=?-EAGAIN; ?????????}?else?????????????ret?=?wait_event_interruptible(thread->wait,?binder_has_thread_work(thread)); ?????} ??????...... ??????while?(1)?{ ?????????uint32_t?cmd; ?????????struct?binder_transaction_data?tr; ?????????struct?binder_work?*w; ?????????struct?binder_transaction?*t?=?NULL; ??????????if?(!list_empty(&thread->todo)) ?????????????w?=?list_first_entry(&thread->todo,?struct?binder_work,?entry); ?????????else?if?(!list_empty(&proc->todo)?&&?wait_for_proc_work) ?????????????w?=?list_first_entry(&proc->todo,?struct?binder_work,?entry); ?????????else?{ ?????????????if?(ptr?-?buffer?==?4?&&?!(thread->looper?&?BINDER_LOOPER_STATE_NEED_RETURN))?/*?no?data?added?*/ ?????????????????goto?retry; ?????????????break; ?????????} ??????????if?(end?-?ptr?<?sizeof(tr)?+?4) ?????????????break; ??????????switch?(w->type)?{ ?????????...... ?????????case?BINDER_WORK_TRANSACTION_COMPLETE:?{ ?????????????cmd?=?BR_TRANSACTION_COMPLETE; ?????????????if?(put_user(cmd,?(uint32_t?__user?*)ptr)) ?????????????????return?-EFAULT; ?????????????ptr?+=?sizeof(uint32_t); ??????????????binder_stat_br(proc,?thread,?cmd); ?????????????if?(binder_debug_mask?&?BINDER_DEBUG_TRANSACTION_COMPLETE) ?????????????????printk(KERN_INFO?"binder:?%d:%d?BR_TRANSACTION_COMPLETE\n", ?????????????????proc->pid,?thread->pid); ??????????????list_del(&w->entry); ?????????????kfree(w); ?????????????binder_stats.obj_deleted[BINDER_STAT_TRANSACTION_COMPLETE]++; ????????????????????????????????????????????????}?break; ?????????...... ?????????} ??????????if?(!t) ?????????????continue; ??????????...... ?????} ??done: ?????...... ?????return?0; ?}? 函數首先是寫入一個操作碼BR_NOOP到用戶傳進來的緩沖區中去。
????? 回憶一下上面的binder_transaction函數,這里的thread->transaction_stack != NULL,并且thread->todo也不為空,所以線程不會進入休眠狀態。
????? 進入while循環中,首先是從thread->todo隊列中取回待處理事項w,w的類型為BINDER_WORK_TRANSACTION_COMPLETE,這也是在binder_transaction函數里面設置的。對BINDER_WORK_TRANSACTION_COMPLETE的處理也很簡單,只是把一個操作碼BR_TRANSACTION_COMPLETE寫回到用戶傳進來的緩沖區中去。這時候,用戶傳進來的緩沖區就包含兩個操作碼了,分別是BR_NOOP和BINDER_WORK_TRANSACTION_COMPLETE。
????? binder_thread_read執行完之后,返回到binder_ioctl函數中,將操作結果寫回到用戶空間中去:
?
if?(copy_to_user(ubuf,?&bwr,?sizeof(bwr)))?{ ?????ret?=?-EFAULT; ?????goto?err; ?}? ??? 最后就返回到IPCThreadState::talkWithDriver函數中了。
?????? IPCThreadState::talkWithDriver函數從下面語句:
?
ioctl(mProcess->mDriverFD,?BINDER_WRITE_READ,?&bwr)? ?? 返回后,首先是清空之前寫入Binder驅動程序的內容:
?
if?(bwr.write_consumed?>?0)?{ ??????if?(bwr.write_consumed?<?(ssize_t)mOut.dataSize()) ???????????mOut.remove(0,?bwr.write_consumed); ??????else???????????mOut.setDataSize(0); ?}? ?? 接著是設置從Binder驅動程序讀取的內容:
if?(bwr.read_consumed?>?0)?{ ??????mIn.setDataSize(bwr.read_consumed); ??????mIn.setDataPosition(0); ?}? ? 然后就返回到IPCThreadState::waitForResponse去了。IPCThreadState::waitForResponse函數的處理也很簡單,就是處理剛才從Binder驅動程序讀入內容了。從前面的分析中,我們知道,從Binder驅動程序讀入的內容就是兩個整數了,分別是BR_NOOP和BR_TRANSACTION_COMPLETE。對BR_NOOP的處理很簡單,正如它的名字所示,什么也不做;而對BR_TRANSACTION_COMPLETE的處理,就分情況了,如果這個請求是異步的,那個整個BC_TRANSACTION操作就完成了,如果這個請求是同步的,即要等待回復的,也就是reply不為空,那么還要繼續通過IPCThreadState::talkWithDriver進入到Binder驅動程序中去等待BC_TRANSACTION操作的處理結果。
????? 這里屬于后一種情況,于是再次通過IPCThreadState::talkWithDriver進入到Binder驅動程序的binder_ioctl函數中。不過這一次在binder_ioctl函數中,bwr.write_size等于0,而bwr.read_size大于0,于是再次進入到binder_thread_read函數中。這時候thread->transaction_stack仍然不為NULL,不過thread->todo隊列已經為空了,因為前面我們已經處理過thread->todo隊列的內容了,于是就通過下面語句:
?
ret?=?wait_event_interruptible(thread->wait,?binder_has_thread_work(thread));? ??? 進入休眠狀態了,等待Service Manager的喚醒。
????? 現在,我們終于可以回到Service Manager被喚醒之后的過程了。前面我們說過,Service Manager此時正在binder_thread_read函數中休眠中:
?
static?int?binder_thread_read(struct?binder_proc?*proc,?struct?binder_thread?*thread, ????????????????????void??__user?*buffer,?int?size,?signed?long?*consumed,?int?non_block) ?{ ?????void?__user?*ptr?=?buffer?+?*consumed; ?????void?__user?*end?=?buffer?+?size; ??????int?ret?=?0; ?????int?wait_for_proc_work; ??????if?(*consumed?==?0)?{ ?????????if?(put_user(BR_NOOP,?(uint32_t?__user?*)ptr)) ?????????????return?-EFAULT; ?????????ptr?+=?sizeof(uint32_t); ?????} ??retry: ?????wait_for_proc_work?=?thread->transaction_stack?==?NULL?&&?list_empty(&thread->todo); ??????...... ??????if?(wait_for_proc_work)?{ ?????????...... ?????????if?(non_block)?{ ?????????????if?(!binder_has_proc_work(proc,?thread)) ?????????????????ret?=?-EAGAIN; ?????????}?else?????????????ret?=?wait_event_interruptible_exclusive(proc->wait,?binder_has_proc_work(proc,?thread)); ?????}?else?{ ?????????...... ?????} ????? ?????...... ??????while?(1)?{ ?????????uint32_t?cmd; ?????????struct?binder_transaction_data?tr; ?????????struct?binder_work?*w; ?????????struct?binder_transaction?*t?=?NULL; ??????????if?(!list_empty(&thread->todo)) ?????????????w?=?list_first_entry(&thread->todo,?struct?binder_work,?entry); ?????????else?if?(!list_empty(&proc->todo)?&&?wait_for_proc_work) ?????????????w?=?list_first_entry(&proc->todo,?struct?binder_work,?entry); ?????????else?{ ?????????????if?(ptr?-?buffer?==?4?&&?!(thread->looper?&?BINDER_LOOPER_STATE_NEED_RETURN))?/*?no?data?added?*/ ?????????????????goto?retry; ?????????????break; ?????????} ??????????if?(end?-?ptr?<?sizeof(tr)?+?4) ?????????????break; ??????????switch?(w->type)?{ ?????????case?BINDER_WORK_TRANSACTION:?{ ?????????????t?=?container_of(w,?struct?binder_transaction,?work); ???????????????????????????????????????}?break; ?????????...... ?????????} ??????????if?(!t) ?????????????continue; ??????????BUG_ON(t->buffer?==?NULL); ?????????if?(t->buffer->target_node)?{ ?????????????struct?binder_node?*target_node?=?t->buffer->target_node; ?????????????tr.target.ptr?=?target_node->ptr; ?????????????tr.cookie?=??target_node->cookie; ?????????????t->saved_priority?=?task_nice(current); ?????????????if?(t->priority?<?target_node->min_priority?&& ?????????????????!(t->flags?&?TF_ONE_WAY)) ?????????????????binder_set_nice(t->priority); ?????????????else?if?(!(t->flags?&?TF_ONE_WAY)?|| ?????????????????t->saved_priority?>?target_node->min_priority) ?????????????????binder_set_nice(target_node->min_priority); ?????????????cmd?=?BR_TRANSACTION; ?????????}?else?{ ?????????????...... ?????????} ?????????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.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); ??????????...... ??????????list_del(&t->work.entry); ?????????t->buffer->allow_user_free?=?1; ?????????if?(cmd?==?BR_TRANSACTION?&&?!(t->flags?&?TF_ONE_WAY))?{ ?????????????t->to_parent?=?thread->transaction_stack; ?????????????t->to_thread?=?thread; ?????????????thread->transaction_stack?=?t; ?????????}?else?{ ?????????????...... ?????????} ?????????break; ?????} ??done: ??????*consumed?=?ptr?-?buffer; ?????...... ?????return?0; ?}? 這里就是從語句中喚醒了:
?
ret?=?wait_event_interruptible_exclusive(proc->wait,?binder_has_proc_work(proc,?thread));? ?? Service Manager喚醒過來看,繼續往下執行,進入到while循環中。首先是從proc->todo中取回待處理事項w。這個事項w的類型是BINDER_WORK_TRANSACTION,這是上面調用binder_transaction的時候設置的,于是通過w得到待處理事務t:
?
t?=?container_of(w,?struct?binder_transaction,?work);? ?? 接下來的內容,就把cmd和t->buffer的內容拷貝到用戶傳進來的緩沖區去了,這里就是Service Manager從用戶空間傳進來的緩沖區了:
?
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);? ?? 注意,這里先是把t->buffer的內容拷貝到本地變量tr中,再拷貝到用戶空間緩沖區去。關于t->buffer內容的拷貝,請參考Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析一文,它的一個關鍵地方是Binder驅動程序和Service Manager守護進程共享了同一個物理內存的內容,拷貝的只是這個物理內存在用戶空間的虛擬地址回去:
?
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?*));? ??? 對于Binder驅動程序這次操作來說,這個事項就算是處理完了,就要從todo隊列中刪除了:
list_del(&t->work.entry);? 緊接著,還不放刪除這個事務,因為它還要等待Service Manager處理完成后,再進一步處理,因此,放在thread->transaction_stack隊列中:
?
t->to_parent?=?thread->transaction_stack; ?t->to_thread?=?thread; ?thread->transaction_stack?=?t;? 還要注意的一個地方是,上面寫入的cmd = BR_TRANSACTION,告訴Service Manager守護進程,它要做什么事情,后面我們會看到相應的分析。
?????? 這樣,binder_thread_read函數就處理完了,回到binder_ioctl函數中,同樣是操作結果寫回到用戶空間的緩沖區中去:
if?(copy_to_user(ubuf,?&bwr,?sizeof(bwr)))?{ ?????ret?=?-EFAULT; ?????goto?err; ?}? ? 最后,就返回到frameworks/base/cmds/servicemanager/binder.c文件中的binder_loop函數去了:
?
void?binder_loop(struct?binder_state?*bs,?binder_handler?func) ?{ ?????int?res; ?????struct?binder_write_read?bwr; ?????unsigned?readbuf[32]; ??????bwr.write_size?=?0; ?????bwr.write_consumed?=?0; ?????bwr.write_buffer?=?0; ????? ?????readbuf[0]?=?BC_ENTER_LOOPER; ?????binder_write(bs,?readbuf,?sizeof(unsigned)); ??????for?(;;)?{ ?????????bwr.read_size?=?sizeof(readbuf); ?????????bwr.read_consumed?=?0; ?????????bwr.read_buffer?=?(unsigned)?readbuf; ??????????res?=?ioctl(bs->fd,?BINDER_WRITE_READ,?&bwr); ??????????if?(res?<?0)?{ ?????????????LOGE("binder_loop:?ioctl?failed?(%s)\n",?strerror(errno)); ?????????????break; ?????????} ??????????res?=?binder_parse(bs,?0,?readbuf,?bwr.read_consumed,?func); ?????????if?(res?==?0)?{ ?????????????LOGE("binder_loop:?unexpected?reply?!\n"); ?????????????break; ?????????} ?????????if?(res?<?0)?{ ?????????????LOGE("binder_loop:?io?error?%d?%s\n",?res,?strerror(errno)); ?????????????break; ?????????} ?????} ?}? ?? 這里就是從下面的語句:
?
res?=?ioctl(bs->fd,?BINDER_WRITE_READ,?&bwr);? ???? 返回來了。接著就進入binder_parse函數處理從Binder驅動程序里面讀取出來的數據:
?
int?binder_parse(struct?binder_state?*bs,?struct?binder_io?*bio, ??????????????????uint32_t?*ptr,?uint32_t?size,?binder_handler?func) ?{ ?????int?r?=?1; ?????uint32_t?*end?=?ptr?+?(size?/?4); ??????while?(ptr?<?end)?{ ?????????uint32_t?cmd?=?*ptr++; ?????????switch(cmd)?{ ?????????...... ?????????case?BR_TRANSACTION:?{ ?????????????struct?binder_txn?*txn?=?(void?*)?ptr; ?????????????...... ?????????????if?(func)?{ ?????????????????unsigned?rdata[256/4]; ?????????????????struct?binder_io?msg; ?????????????????struct?binder_io?reply; ?????????????????int?res; ??????????????????bio_init(&reply,?rdata,?sizeof(rdata),?4); ?????????????????bio_init_from_txn(&msg,?txn); ?????????????????res?=?func(bs,?txn,?&msg,?&reply); ?????????????????binder_send_reply(bs,?&reply,?txn->data,?res); ?????????????} ?????????????ptr?+=?sizeof(*txn)?/?sizeof(uint32_t); ?????????????break; ??????????????????????????????} ?????????...... ?????????default: ?????????????LOGE("parse:?OOPS?%d\n",?cmd); ?????????????return?-1; ?????????} ?????} ??????return?r; ?}? 前面我們說過,Binder驅動程序寫入到用戶空間的緩沖區中的cmd為BR_TRANSACTION,因此,這里我們只關注BR_TRANSACTION相關的邏輯。
???????? 這里用到的兩個數據結構struct binder_txn和struct binder_io可以參考前面一篇文章Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析,這里就不復述了。
???????? 接著往下看,函數調bio_init來初始化reply變量:
?
void?bio_init(struct?binder_io?*bio,?void?*data, ???????????????uint32_t?maxdata,?uint32_t?maxoffs) ?{ ?????uint32_t?n?=?maxoffs?*?sizeof(uint32_t); ??????if?(n?>?maxdata)?{ ?????????bio->flags?=?BIO_F_OVERFLOW; ?????????bio->data_avail?=?0; ?????????bio->offs_avail?=?0; ?????????return; ?????} ??????bio->data?=?bio->data0?=?data?+?n; ?????bio->offs?=?bio->offs0?=?data; ?????bio->data_avail?=?maxdata?-?n; ?????bio->offs_avail?=?maxoffs; ?????bio->flags?=?0; ?}? ?? 最后,真正進行處理的函數是從參數中傳進來的函數指針func,這里就是定義在frameworks/base/cmds/servicemanager/service_manager.c文件中的svcmgr_handler函數:
?
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; ??//????LOGI("target=%p?code=%d?pid=%d?uid=%d\n", ?//?????????txn->target,?txn->code,?txn->sender_pid,?txn->sender_euid); ??????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_GET_SERVICE: ?????case?SVC_MGR_CHECK_SERVICE: ?????????s?=?bio_get_string16(msg,?&len); ?????????ptr?=?do_find_service(bs,?s,?len); ?????????if?(!ptr) ?????????????break; ?????????bio_put_ref(reply,?ptr); ?????????return?0; ??????...... ?????} ?????default: ?????????LOGE("unknown?code?%d\n",?txn->code); ?????????return?-1; ?????} ??????bio_put_uint32(reply,?0); ?????return?0; ?}? ??? 這里, Service Manager要處理的code是SVC_MGR_CHECK_SERVICE,這是在前面的BpServiceManager::checkService函數里面設置的。
??????? 回憶一下,在BpServiceManager::checkService時,傳給Binder驅動程序的參數為:
?
writeInt32(IPCThreadState::self()->getStrictModePolicy()?|?STRICT_MODE_PENALTY_GATHER);?? ?writeString16("android.os.IServiceManager");?? ?writeString16("media.player");??? ?? 這里的語句:
?
strict_policy?=?bio_get_uint32(msg);?? ?s?=?bio_get_string16(msg,?&len);?? ?s?=?bio_get_string16(msg,?&len);?? ???? 其中,會驗證一下傳進來的第二個參數,即"android.os.IServiceManager"是否正確,這個是驗證RPC頭,注釋已經說得很清楚了。
?????? 最后,就是調用do_find_service函數查找是存在名稱為"media.player"的服務了?;貞浺幌虑懊嬉黄恼翧ndroid系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析,MediaPlayerService已經把一個名稱為"media.player"的服務注冊到Service Manager中,所以這里一定能找到。我們看看do_find_service這個函數:
?
void?*do_find_service(struct?binder_state?*bs,?uint16_t?*s,?unsigned?len) ?{ ?????struct?svcinfo?*si; ?????si?=?find_svc(s,?len); ??//????LOGI("check_service('%s')?ptr?=?%p\n",?str8(s),?si???si->ptr?:?0); ?????if?(si?&&?si->ptr)?{ ?????????return?si->ptr; ?????}?else?{ ?????????return?0; ?????} ?}? ? 這里又調用了find_svc函數:
?
struct?svcinfo?*find_svc(uint16_t?*s16,?unsigned?len) ?{ ?????struct?svcinfo?*si; ??????for?(si?=?svclist;?si;?si?=?si->next)?{ ?????????if?((len?==?si->len)?&& ?????????????!memcmp(s16,?si->name,?len?*?sizeof(uint16_t)))?{ ?????????????return?si; ?????????} ?????} ?????return?0; ?}? 就是在svclist列表中查找對應名稱的svcinfo了。
?????? 然后返回到do_find_service函數中?;貞浺幌虑懊嬉黄恼翧ndroid系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析,這里的si->ptr就是指MediaPlayerService這個Binder實體在Service Manager進程中的句柄值了。
?????? 回到svcmgr_handler函數中,調用bio_put_ref函數將這個Binder引用寫回到reply參數。我們看看bio_put_ref的實現:
?
void?bio_put_ref(struct?binder_io?*bio,?void?*ptr) ?{ ?????struct?binder_object?*obj; ??????if?(ptr) ?????????obj?=?bio_alloc_obj(bio); ?????else?????????obj?=?bio_alloc(bio,?sizeof(*obj)); ??????if?(!obj) ?????????return; ??????obj->flags?=?0x7f?|?FLAT_BINDER_FLAG_ACCEPTS_FDS; ?????obj->type?=?BINDER_TYPE_HANDLE; ?????obj->pointer?=?ptr; ?????obj->cookie?=?0; ?}? ?? 這里很簡單,就是把一個類型為BINDER_TYPE_HANDLE的binder_object寫入到reply緩沖區中去。這里的binder_object就是相當于是flat_binder_obj了,具體可以參考Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析一文。
??????? 再回到svcmgr_handler函數中,最后,還寫入一個0值到reply緩沖區中,表示操作結果碼:
bio_put_uint32(reply,?0);? ??? 最后返回到binder_parse函數中,調用binder_send_reply函數將操作結果反饋給Binder驅動程序:
?
void?binder_send_reply(struct?binder_state?*bs, ????????????????????????struct?binder_io?*reply, ????????????????????????void?*buffer_to_free, ????????????????????????int?status) ?{ ?????struct?{ ?????????uint32_t?cmd_free; ?????????void?*buffer; ?????????uint32_t?cmd_reply; ?????????struct?binder_txn?txn; ?????}?__attribute__((packed))?data; ??????data.cmd_free?=?BC_FREE_BUFFER; ?????data.buffer?=?buffer_to_free; ?????data.cmd_reply?=?BC_REPLY; ?????data.txn.target?=?0; ?????data.txn.cookie?=?0; ?????data.txn.code?=?0; ?????if?(status)?{ ?????????data.txn.flags?=?TF_STATUS_CODE; ?????????data.txn.data_size?=?sizeof(int); ?????????data.txn.offs_size?=?0; ?????????data.txn.data?=?&status; ?????????data.txn.offs?=?0; ?????}?else?{ ?????????data.txn.flags?=?0; ?????????data.txn.data_size?=?reply->data?-?reply->data0; ?????????data.txn.offs_size?=?((char*)?reply->offs)?-?((char*)?reply->offs0); ?????????data.txn.data?=?reply->data0; ?????????data.txn.offs?=?reply->offs0; ?????} ?????binder_write(bs,?&data,?sizeof(data)); ?}?
總結
以上是生活随笔為你收集整理的Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析(2)...的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。