android Binder設計與實現三

4.3 struct binder_transaction_data :收發數據包結構

該結構是Binder接收/發送數據包的標準格式,每個成員定義如下:

表 5 Binder收發數據包結構:binder_transaction_data

  

成員 含義
union {
size_t handle;
void *ptr;
} target;
對於發送數據包的一方,該成員指明發送目的地。由於目的是在遠端,所以這裡填入的是對Binder實體的引用,存放在target.handle 中。如前述,Binder的引用在代碼中也叫句柄(handle)。
當數據包到達接收方時,驅動已將該成員修改成Binder實體,即指向Binder對象內存的指針,使用target.ptr來獲得。該指針是接收方在將Binder實體傳輸給其它進程時提交給驅動的,驅動程序能夠自動將發送方填入的引用轉換成接收方Binder對象的指針,故接收方可以直接將其當做對象指針來使用(通常是將其reinterpret_cast成相應類)。
void *cookie; 發送方忽略該成員;接收方收到數據包時,該成員存放的是創建Binder實體時由該接收方自定義的任意數值,做為與Binder指針相關的額外信息存放在驅動中。驅動基本上不關心該成員。
unsigned int code; 該成員存放收發雙方約定的命令碼,驅動完全不關心該成員的內容。通常是Server端定義的公共接口函數的編號。
unsigned int flags; 與交互相關的標志位,其中最重要的是TF_ONE_WAY位。如果該位置上表明這次交互是異步的,接收方不會返回任何數據。驅動利用該位來決定是否構建與返回有關的數據結構。另外一位TF_ACCEPT_FDS是出於安全考慮,如果發起請求的一方不希望在收到的回復中接收文件形式的Binder可以將該位置上。因為收到一個文件形式的Binder會自動為接收方打開一個文件,使用該位可以防止打開文件過多。
pid_t sender_pid;
uid_t sender_euid;
該成員存放發送方的進程ID和用戶ID,由驅動負責填入,接收方可以讀取該成員獲知發送方的身份。
size_t data_size; 該成員表示data.buffer指向的緩沖區存放的數據長度。發送數據時由發送方填入,表示即將發送的數據長度;在接收方用來告知接收到數據的長度。
size_t offsets_size; 驅動一般情況下不關心data.buffer裡存放什麼數據,但如果有Binder在其中傳輸則需要將其相對data.buffer的偏移位置指出來讓驅動知道。有可能存在多個Binder同時在數據中傳遞,所以須用數組表示所有偏移位置。本成員表示該數組的大小。
union {
struct {
const void *buffer;
const void *offsets;
} ptr;
uint8_t buf[8];
} data;
data.bufer存放要發送或接收到的數據;data.offsets指向Binder 偏移位置數組,該數組可以位於data.buffer 中,也可以在另外的內存空間中,並無限制。buf[8]是為瞭無論保證32位還是64位平臺,成員data

 

這裡有必要再強調一下offsets_size和data.offsets兩個成員,這是Binder通信有別於其它IPC的地方。如前 述,Binder采用面向對象的設計思想,一個Binder實體可以發送給其它進程從而建立許多跨進程的引用;另外這些引用也可以在進程之間傳遞,就象 java裡將一個引用賦給另一個引用一樣。為Binder在不同進程中建立引用必須有驅動的參與,由驅動在內核創建並註冊相關的數據結構後接收方才能使用該引用。而且這些引用可以是強類型,需要驅動為其維護引用計數。然而這些跨進程傳遞的Binder混雜在引用程序發送的數據包裡,數據格式完全由用戶定義,如果不把它們一一標記出來告知驅動,驅動將無法從數據中將它們提取出來。於是就使用數組data.offsets存放用戶數據中每個Binder相對 data.buffer的偏移量,用offsets_size表示這個數組的大小。驅動在發送數據包時會根據data.offsets和 offset_size將散落於data.buffer中的Binder找出來並一一為它們創建相關的數據結構。在數據包中傳輸的Binder是類型為 struct flat_binder_object的結構體,詳見後文。

對於接收方來說,該結構隻相當於一個定長的消息頭,真正的用戶數據存放在data.buffer所指向的緩存區中。如果發送方在數據中內嵌瞭一個或 多個Binder,接收到的數據包中同樣會用data.offsets和offset_size指出每個Binder的位置和總個數。不過通常接收方可以 忽略這些信息,因為接收方是知道數據格式的,參考雙方約定的格式定義就能知道這些Binder在什麼位置。

 

 

圖 2 BINDER_WRITE_READ數據包實例

 

摘自 LuoXianXiong,您的夥伴

發佈留言