這裏以註冊服務爲例,當led_control_service
請求註冊服務時是經過handle找到的ServiceManager
,可是ServiceManager
是如何找到led_control_service
進行回覆的呢?node
答:這裏驅動中用到了一個傳送棧記錄了發送和接收進程,線程的信息; 接下來咱們講下具體的流程;async
主要代碼在binder_transaction()
和binder_thread_read()
中;函數
從led_control_service
調用BC_TRANSACTION
開始,此時驅動會調用binder_transaction()
函數; ui
以下是該函數中的一段代碼,這段代碼前面在深刻驅動時未講解:線程
if (!reply && !(tr->flags & TF_ONE_WAY)) ① t->from = thread; else t->from = NULL; t->sender_euid = task_euid(proc->tsk); t->to_proc = target_proc; ② t->to_thread = target_thread; t->code = tr->code; t->flags = tr->flags; t->priority = task_nice(current);
①: 判斷是否須要回覆,須要則記錄下當前進程的thread信息;
②: 記錄下要目標進程信息和線程信息;
這裏t
是struct binder_transaction
結構,和transaction_stack
類型相同;debug
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; ..... };
①: 記錄發送線程信息;
②: 記錄發送線程的傳輸棧的父棧;
③: 記錄接收進程的進程信息;
④: 記錄接收線程的進程信息;
⑤: 記錄接收進程的傳輸棧的父棧;
此時t
變量中的主要信息以下:code
transaction_starck | |
---|---|
from | led_control_service'thread |
to_proc | ServiceManager |
to_thread | ServiceManager'thread |
此時已經記錄下了接收方的信息了,繼續往下看(binder_transaction()
函數內):server
if (reply) { BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction(target_thread, in_reply_to); } else if (!(t->flags & TF_ONE_WAY)) { ① BUG_ON(t->buffer->async_transaction != 0); t->need_reply = 1; t->from_parent = thread->transaction_stack; ② thread->transaction_stack = t; ③ } else { BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); if (target_node->has_async_transaction) { target_list = &target_node->async_todo; target_wait = NULL; } else target_node->has_async_transaction = 1; }
①: 判斷是否須要回覆;
②: 這裏一個入棧操做將當前線程的傳輸壓入,可是thread->transaction_stack
此時爲NULL
,由於第一次執行前面沒有賦值;
③: 接下給當前線程的傳輸棧賦值,;
此時led_control_service
線程的傳輸棧信息以下:進程
transaction_starck | |
---|---|
from | led_control_service'thread |
to_proc | ServiceManager |
to_thread | ServiceManager'thread |
from_parent | NULL |
前面驅動講解過,在led_contrl_server
執行binder_transaction()
後,ServiceManager
的進程會被喚醒,則ServiceManager
會從休眠中醒來繼續執行binder_thread_read
; 事務
binder_thread_read
有段代碼以下:
if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) { t->to_parent = thread->transaction_stack; ① t->to_thread = thread; ② thread->transaction_stack = t; ③ } else { t->buffer->transaction = NULL; kfree(t); binder_stats_deleted(BINDER_STAT_TRANSACTION); }
①: 將當前線程傳輸棧入棧;
②: 記錄接收進程的信息,也就是本身自己,由於他自己是被喚醒的;
③: 當前線程傳輸棧記錄下線程信息;
這裏的t
是從帶處理事務的鏈表中取出來的,也就是前面led_control_service
掛到ServiceManager
的todo鏈表上;
則ServiceManager
線程的傳輸棧的信息以下:
transaction_starck | |
---|---|
from | led_control_service'thread |
to_proc | ServiceManager |
to_thread | ServiceManager'thread |
from_parent | NULL |
to_parent | NULL |
到這裏線程傳輸棧的數據來源和構造講完;
ServiceManager
的用戶態在處理完註冊信息後,調用BC_REPLAY
命令回覆註冊結果給led_control_service
,此時驅動中也是調用到binder_transaction()
;
binder_transaction
代碼片以下:
if (reply) { in_reply_to = thread->transaction_stack; ① ALOGD("%s:%d,%d %s in_reply_to = thread->transaction_stack\n", proc->tsk->comm, proc->pid, thread->pid, __FUNCTION__); if (in_reply_to == NULL) { binder_user_error("%d:%d got reply transaction with no transaction stack\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; goto err_empty_call_stack; } binder_set_nice(in_reply_to->saved_priority); if (in_reply_to->to_thread != thread) { ② return_error = BR_FAILED_REPLY; in_reply_to = NULL; goto err_bad_call_stack; } thread->transaction_stack = in_reply_to->to_parent; ③ target_thread = in_reply_to->from; ④ if (target_thread == NULL) { return_error = BR_DEAD_REPLY; goto err_dead_binder; } if (target_thread->transaction_stack != in_reply_to) { return_error = BR_FAILED_REPLY; in_reply_to = NULL; target_thread = NULL; goto err_dead_binder; } target_proc = target_thread->proc; } else {
①: 用個臨時變量記錄下當前線程額傳輸棧信息;
②: 判斷下接收的線程是否爲本身自己,若是不是則出錯,看迷糊的能夠看下再2.2節;
③: 一次出棧操做,此時thread->transaction_stack
值爲NULL
了;
④: 獲取到目標線程,from
中記錄着發送線程led_contol_service
的信息;
這裏就經過ServiceManager
在read的時候入棧的傳送棧信息,獲取到發送進程的信息,即回覆進程的信息;
接着往下看:
if (reply) { BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction(target_thread, in_reply_to); ① } else if (!(t->flags & TF_ONE_WAY)) { BUG_ON(t->buffer->async_transaction != 0); t->need_reply = 1; t->from_parent = thread->transaction_stack; thread->transaction_stack = t; } else { ... }
①: 一個出棧操做;
此時led_control_service
的傳輸棧也指向了父棧,即爲空且清除了in_reply_to
中from
的信息;
上面那部ServiceManager
進程已經知道此時要發送給誰,到此該問題就完美解答了;