Binder是通過AIDL來描述進程間通信的接口的,Binder作為一個特殊的字符設備,設備節(jié)點是/dev/binder。
一張從大牛那搬來的圖,很形象也解釋了很多東西。

在驅動程序中有幾個數據結構還是很有必要分析一下的
kernel/goldfish/drivers/staging/android/binder.c
1 binder_work
struct binder_work{
struct list_head entry;
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;
}
}
該結構體用來描述待處理的工作項,這些工作項有可能屬于一個進程,也可能屬于某個進程的線程。成員entry 用來將這些結構體嵌入到宿主結構中,成員變量type用來描述工作項的類型。根據type的取值,binder驅動程序可以判斷出一個binder_work嵌入到什么類型的宿主結構中。
2 binder_node
struct binder_node {
int debug_id;
struct binder_work work;
union {
struct rb_node rb_node; // 如果這個Binder實體還在使用,則將該節(jié)點鏈接到proc->nodes中。相當于紅黑二叉樹的節(jié)點
struct hlist_node dead_node; // 如果這個Binder實體所屬的進程已經銷毀,而這個Binder實體又被其它進程所引用,則這個Binder實體通過dead_node進入到一個哈希表中去存放
};
struct binder_proc *proc; // 該binder實體所屬的Binder進程
struct hlist_head refs; // 該Binder實體的所有Binder引用所組成的鏈表 int
//強引用計數和弱引用計數管理Binder對象生命周期
internal_strong_refs;
int local_weak_refs;
int local_strong_refs;
void __user *ptr; // Binder實體在用戶空間的地址(為Binder實體對應的Server在用戶空間的本地Binder的引用)
void __user *cookie; // Binder實體在用戶空間的其他數據(為Binder實體對應的Server在用戶空間的本地Binder自身)
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;
};
binder_node用來描述Binder實體對象。每一個Service在驅動程序中都對應一個Binder實體對象,用來描述他在內核中的狀態(tài)。
- ** proc:指向一個Binder實體對象的宿主進程*。
- rb_node: 宿主進程是通過一個紅黑二叉樹來管理binder實體對象的,而這個成員變量就是這個紅黑二叉樹的一個節(jié)點
- dead_node:如果Binder實體對象的宿主進程死亡,但是這個這個Binder實體對象需要暫存一下自己,這樣不用再次使用原宿主進程的時候再重新創(chuàng)建Binder實體對象,所以它通過變量dead_node來將自己保存在一個全局的hash類表中。
-
refs: Binder實體對象有可能被多個
Client組件引用,所以需要使用refs來描述這些引用關系,并且將它們保存在同一個hash列表中。Binder驅動可以通過它知道那些client組件引用了同一個Binder實體對象。 - ** cookie*:指向該
Service組件的地址 - ** ptr:指向該
Service組件內部的一個引用計數對象*的地址 - has_async_transaction:用來描述一個Binder實體對象是否正在處理一個異步事務,如果是則他的值等于1。
- aysnc_todo:描述異步事務隊列。每一個事務都關聯(lián)著一個Binder實體對象,要求這個Binder實體對象對應的Service組件在指定的線程中處理該事物。但是異步事務只會有一個得到處理,所以其余等待的異步事務都保存在該隊列中。
- accept_fds:用來描述一個Binder實體對象是否可以接收包含有文件描述符的進程通信你數據,1表示可以
- min_priority : 表示Binder實體對象在處理一個來自Client進程的請求時,他所要求的處理線程(即Server進程中的一個線程)應該具備的最小線程優(yōu)先級。
Binder驅動通過強應用和弱引用技術來維護他們的生命周期。internal_strong_refs和local_strong_refs均是用來描述一個Binder實體的強引用計數;local_weak_refs用來描述弱引用計數。當Binder實體對象請求一個Service組件來執(zhí)行某一個操作時,會增加強引用計數或弱引用計數,相應的has_strong_ref和has_weak_ref的值會至[1]。當Service組件完成操作后,就會減少強引用或者弱引用計數。Binder實體對象在請求Service組件增加或減少強引用(或弱引用)計數的過程中 pending_strong_ref和pending_weak_ref的值置[1],使用之后Binder實體對象會將這兩個成員變量的值設置為[0]。當引用計數0變1或1變0時,work的值就變?yōu)?strong>BINDER_WORK_NODE,并將它添加到todo隊列中等待處理
3 binder_ref
struct binder_ref {
int debug_id;
struct rb_node rb_node_desc; // 關聯(lián)到binder_proc->refs_by_desc紅黑樹中
struct rb_node rb_node_node; // 關聯(lián)到binder_proc->refs_by_node紅黑樹中
struct hlist_node node_entry; // 關聯(lián)到binder_node->refs哈希表中,hash列表的節(jié)點
struct binder_proc *proc; // 該Binder引用所屬的Binder進程
struct binder_node *node; // 該Binder引用對應的Binder實體
uint32_t desc; // 描述
int strong; //強引用計數
int weak; //弱引用計數
struct binder_ref_death *death; //指向一個Service組件的死亡通知
};
前面有介紹是用來描述Binder引用對象。宿主進程使用兩個紅黑樹來保存它內部所有的Binder引用對象。分別是句柄值(用來描述一個Binder引用對象)和Binder實體對象的地址,rb_node_desc和rb_node_node就正好是這兩個紅黑樹的節(jié)點。
4 binder_ref_death
struct binder_ref_death{
struct binder_work work;
void _user *cookie; //保存負責接受死亡通知的對象的地址
}
用來描述一個Service組件的死亡通知。
因為Client無法控制他所引用的Service組件的生命周期,所以當Service意外崩潰的時候只能向Binder驅動程序中注冊一個死亡通知,將其保存在cookie指正指向位置。然后根據這個通知work會取相應的值。
5 binder_buffer
struct binder_buffer {
struct list_head entry; // 和binder_proc->buffers關聯(lián)到同一鏈表,從而使Binder進程對內存進行管理。
struct rb_node rb_node; // 和binder_proc->free_buffers或binder_proc->allocated_buffers關聯(lián)到同一紅黑樹,從而對已有內存和空閑內存進行管理。
unsigned free:1; // 空閑與否的標記
unsigned allow_user_free:1;
unsigned async_transaction:1; //異步事務置"1"
unsigned debug_id:29;
struct binder_transaction *transaction; //描述該緩沖區(qū)正在交給那個緩沖區(qū)處理
struct binder_node *target_node; //目標Binder實體對象
size_t data_size;
size_t offsets_size;
uint8_t data[0];};
描述一個內核緩沖區(qū),用來在進程件傳遞數據。
6. binder_proc
struct binder_proc {
struct hlist_node proc_node; // 根據proc_node,可以獲取該進程在"全局哈希表binder_procs(統(tǒng)計了所有的binder proc進程)"中的位置
struct rb_root threads; // binder_proc進程內用于處理用戶請求的線程組成的紅黑樹(關聯(lián)binder_thread->rb_node)
struct rb_root nodes; // binder_proc進程內的binder實體組成的紅黑樹(關聯(lián)binder_node->rb_node)
struct rb_root refs_by_desc; // binder_proc進程內的binder引用組成的紅黑樹,該引用以句柄來排序(關聯(lián)binder_ref->rb_node_desc)
struct rb_root refs_by_node; // binder_proc進程內的binder引用組成的紅黑樹,該引用以它對應的binder實體的地址來排序(關聯(lián)binder_ref->rb_node)
int pid; // 進程id
struct vm_area_struct *vma; // 進程的內核虛擬內存
struct mm_struct *vma_vm_mm;
struct task_struct *tsk; // 進程控制結構體(每一個進程都由task_struct 數據結構來定義)。
struct files_struct *files; // 保存了進程打開的所有文件表數據
struct hlist_node deferred_work_node; int deferred_work; void *buffer; // 該進程映射的物理內存在內核空間中的起始位置
ptrdiff_t user_buffer_offset; // 內核虛擬地址與進程虛擬地址之間的差值 // 內存管理的相關變量
struct list_head buffers; // 和binder_buffer->entry關聯(lián)到同一鏈表,從而對Binder內存進行管理
struct rb_root free_buffers; // 空閑內存,和binder_buffer->rb_node關聯(lián)。
struct rb_root allocated_buffers; // 已分配內存,和binder_buffer->rb_node關聯(lián)。
size_t free_async_space; struct page **pages; // 映射內存的page頁數組,page是描述物理內存的結構體
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; // 最大線程數。定義threads中可包含的最大進程數。 int requested_threads;
int requested_threads_started;
int ready_threads;
long default_priority; // 默認優(yōu)先級。
struct dentry *debugfs_entry;
};
該結構體用來描述一個正在使用Binder進程間通信機制的進程。可以借此查考一下如何用結構體內來描述一個進程
7. binder_thread
struct binder_thread {
struct binder_proc *proc; // 線程所屬的Binder進程
struct rb_node rb_node; // 紅黑樹節(jié)點,關聯(lián)到紅黑樹binder_proc->threads中。
int pid; // 進程id int looper; // 線程狀態(tài)??梢匀INDER_LOOPER_STATE_REGISTERED等值
struct binder_transaction *transaction_stack; // 正在處理的事務棧
struct list_head todo; // 待處理的事務鏈表
uint32_t return_error; /* Write failed, return error code in read buf */
uint32_t return_error2; /* Write failed, return error code in read */
wait_queue_head_t wait; // 等待隊列
struct binder_stats stats; // 保存一些統(tǒng)計信息};
該結構用來描述一個線程池中的一個線程
8. binder_transaction
struct binder_transaction{
int debug_id;
struct binder_work work; //當Binder驅動程序為目標進程或者目標線程創(chuàng)建一個事務時,就會將work的值設置為BINDER_WORK_TRANSACTION
struct binder_thread *from; //發(fā)起事務線程,稱為源線程
sturct binder_proc *to_proc; //負責處理該事物的進程
sturct binder_thread *to_thread; //負責處理該事物的線程
struct binser_transaction *from_parent; //依賴事務
struct binder_transaction *to_parent; //目標線程需要處理的下一個事務
unsigned need_reply : 1; //區(qū)分事務是同步還是異步;1表示同步事務,需要等待對方回應。
struct binder_buffer *buffer; //驅動程序為該事務分配的一塊內核緩沖區(qū)
unsigned int code;
unsigned int flags;
long priority; //源線程優(yōu)先級
long saved_priority; //線程處理一個事務時,需要先修改他的線程優(yōu)先級,來滿足Service組件的要求,所以需要使用這個變量來保存原先的優(yōu)先級
uid_t sender_euid; //用戶ID
};
該結構提用來描述進程間通信過程,又叫事務。
9. binder_write_read
struct binder_write_read {
signed long write_size;
signed long write_consumed;
unsigned long write_buffer;
signed long read_size;
signed long read_consumed;
unsigned long read_buffer;
};
該結構體用來描述進程間通信過程中所傳輸的數據。write_buffer和read_buffer都是一個數組,數組的每一個元素都是由一個通信協(xié)議代碼及其通信數據組成。
10.binder_transaction_data
struct binder_transaction_data {
union {
size_t handle; // 當binder_transaction_data是由用戶空間的進程發(fā)送給Binder驅動時,
// handle是該事務的發(fā)送目標在Binder驅動中的信息,即該事務會交給handle來處理;
// handle的值是目標在Binder驅動中的Binder引用。
void *ptr; // 當binder_transaction_data是有Binder驅動反饋給用戶空間進程時,
// ptr是該事務的發(fā)送目標在用戶空間中的信息,即該事務會交給ptr對應的服務來處理;
// ptr是處理該事務的服務的服務在用戶空間的本地Binder對象。
} target; // 該事務的目標對象(即,該事務數據包是給該target來處理的)
void *cookie; // 只有當事務是由Binder驅動傳遞給用戶空間時,cookie才有意思,它的值是處理該事務的Server位于C++層的本地Binder對象
unsigned int code; // 事務編碼。如果是請求,則以BC_開頭;如果是回復,則以BR_開頭。
unsigned int flags; //標志值,用來描述京城間通信行為特征
pid_t sender_pid; //發(fā)起進程間通信請求的進程的PID
uid_t sender_euid; //發(fā)起進程間通信請求的進程的UID
size_t data_size; // 數據大小
size_t offsets_size; // 數據中包含的對象的個數
union {
struct {
const void *buffer;
const void *offsets;
} ptr; //
uint8_t buf[8];
} data; // 數據
};
該結構體用來描述進程間通信過程中所傳輸的數據
11.flat_binder_object
struct flat_binder_object {
unsigned long type; // binder類型:可以為BINDER_TYPE_BINDER或BINDER_TYPE_HANDLE等類型
unsigned long flags; // 標記
union {
void *binder; // 當type=BINDER_TYPE_BINDER時,它指向Binder對象位于C++層的本地Binder對象(即BBinder對象)的弱引用。
signed long handle; // 當type=BINDER_TYPE_HANDLE時,它等于Binder對象在Binder驅動中對應的Binder實體的Binder引用的描述。
};
void *cookie; // 當type=BINDER_TYPE_BINDER時才有效,它指向Binder對象位于C++層的本地Binder對象(即BBinder對象)。
};
該結構體除了可以描述一個Binder實體對象和Binder引用對象之外,還可以用來描述一個文件描述符,可以通過type來區(qū)別
通信協(xié)議代碼
kerner/goldfish/drivers/staging/android/binder.h
1. BinderDriverCommandProtocol
命令協(xié)議代碼,在輸入緩沖區(qū)write_buffer中使用
2. BinderDriverReturnProtocol
返回協(xié)議代碼,在輸出緩沖區(qū)read_buffer中使用
內容有點枯燥,但是對于后面的學習很有幫助
</br>
</br>
參考:
http://wangkuiwu.github.io/2014/09/02/Binder-Datastruct/#anchor1_7
《Android系統(tǒng)源代碼情景分析》羅升陽大神著