天天看點

05.Binder系統:第6課第7節_Binder系統_驅動情景分析_transaction_stack機制_REPLY

通過前面的學習我們知道,binder通信涉及搭配兩個程序,A,B:

05.Binder系統:第6課第7節_Binder系統_驅動情景分析_transaction_stack機制_REPLY

A發送一個BC_TRANSACTION消息給驅動,驅動把其轉化為BR_TRANSACTIONB轉發給B。

B接收到一個類型為BR_TRANSACTIONB的資料,然後發送一個BC_REPLY的消息給驅動,驅動把其轉化為BR_REPLY,然後回複給A程序。

簡單概述

在前面的分析中,我們沒有詳細的分析,驅動程式中,如何查找到消息的目的程序。該小節我們進行詳細的分析。主要解決以下兩個問題即可:

1.發給誰?handle隻表明了程序,是發送給程序,還是發送給線程?

2.回複給誰?回複的時候沒有了handle表明目的程序,必定在某個地方記錄了發送者(即後面要講解的transaction_stack)

在擷取服務的時候,我們獲得的handle代表一個程序,但是需要發送的目标可能是某個線程。

05.Binder系統:第6課第7節_Binder系統_驅動情景分析_transaction_stack機制_REPLY

如test_client要發送資料給test_sever。

test_sever中存在多個線程(binder_thread),其在binder驅動中,對應一個binder_proc結構體,并且還有一個todo連結清單。但是binder_thread中也存在一個todo連結清單。那麼問題來了,發送資料的時候,我們是把資料放入binder_proc的todo連結清單還是放入binder_thread的todo連結清單呢?

一般來說,test_client會把資料放入到binder_proc的todo連結清單中,喚醒等待于binder_proc.wait的空閑線程。但是也有特殊情況,對于雙向傳輸,則放在binder_thread.todo中,然後喚醒該線程。那怎麼分辨是否為雙向傳輸呢?其也是通過該小節要講解的transaction_stack機制來判斷。

下面我們進行情景分析。

情景分析

下面是一個test_client與test_server執行的流程圖:

05.Binder系統:第6課第7節_Binder系統_驅動情景分析_transaction_stack機制_REPLY

test_client發送一個BC_TRANSACTION,test_server接收到一個BR_TRANSACTION。test_server處理完成之後發送BC_REPLY給test_client,test_client接收到一個BR_REPLY。

根據這四個過程,我們看看transaction_stack是如何其作用的,前面分析過,binder_ioctl最終會調用到binder_transaction()函數,

static void binder_transaction(struct binder_proc *proc,struct binder_thread *thread,struct binder_transaction_data *tr, int reply,binder_size_t extra_buffers_size)
	if (reply) {
		......
	} else {
		struct binder_ref *ref;
		/*根據tr->target.handle獲得一個struct binder_ref *ref*/
		ref = binder_get_ref_olocked(proc, tr->target.handle,true);
		/*根據ref獲得struct binder_node *target_node,即目的節點*/
		target_node = binder_get_node_refs_for_txn(ref->node, &target_proc,&return_error);
		......
		......
           

下面是一個詳細的框圖,我們圍繞該框圖進行講解:

05.Binder系統:第6課第7節_Binder系統_驅動情景分析_transaction_stack機制_REPLY

BC_TRANSACTION過程

1.在一看是的時候,test_client與test_server是非雙向傳輸的,是以資料将放在test_server的binder_proc.todo的連結清單中,喚醒test_server.binder_proc.wait上等待到得線程

static void binder_transaction(struct binder_proc *proc,struct binder_thread *thread,struct binder_transaction_data *tr, int reply,binder_size_t extra_buffers_size)
	/*發送之後還想得到回複*/
	} else if (!(t->flags & TF_ONE_WAY)) {
		/*一個連結清單的操作,入棧。t中包含了甚多資訊,如發送給誰,從哪裡開始發送等等*/
		t->from_parent = thread->transaction_stack;
	/*程序在沒有建立線線程的時候,也存在一個主線程*/
	binder_enqueue_work(proc, tcomplete, &thread->todo);
           

2.test_client中的binder_thread存在.transaction_stack指向一個傳輸結構。

05.Binder系統:第6課第7節_Binder系統_驅動情景分析_transaction_stack機制_REPLY

BC_TRANSACTION過程

test_server接收到BR_TRANSACTION之後:

05.Binder系統:第6課第7節_Binder系統_驅動情景分析_transaction_stack機制_REPLY

繼續閱讀