結構體binder_node用來描述一個Binder實體對象。每個Service組件在Binder驅動程序中都對應有一個Binder實體對象,用來描述它在內核中的狀態。Binder驅動程序經過強引用計數和弱引用計數技術來維護它們的生命週期。node
結構體binder_proc用來描述一個正在使用Binder進程間通訊機制的進程。當一個進程調用函數open來打開設備文件/dev/binder時,Binder驅動程序就會爲它建立一個binder_proc結構體,而且將它保存在一個全局的hash列表中linux
proc_node :hash列表中的當前節點。數組
delivered_death : 當一個進程所引用的Service組件死亡時,Binder驅動程序就會向該進程發送一個死亡通知。這個正在發出的死亡通知被封裝成一個類型爲BINDER_WORK_DEAD_BINDER或者BINDER_WORK_DEAD_BINDER_AND_CLEAR的工做項,而且保存在由成員變量delivered_death所描述的一個隊列中,表示Binder驅動程序正在向進程發送的死亡通知。當進程接收到這個死亡通知以後,它便會通知Binder驅動程序,這時候Binder驅動程序就會將對應的工做項從成員變量delivered_death所描述的隊列中刪除。安全
stats : 進程binder通訊統計數據cookie
pid: 進程組idapp
task: 進程的任務控制塊(linux的內容)異步
files: async
default_priority:進程默認的優先級,當一個線程處理一個工做項時,它的線程優先級有可能會被設置爲其宿主進程的優先級。ide
buffer_size ,buffer , vma ,user_buffer_offset , pages : 進程打開了設備文件/dev/binder以後,還必須調用函數mmap將它映射到進程的地址空間來,其實是請求Binder驅動程序爲它分配一塊內核緩衝區,以即可以用來在進程間傳輸數據。Binder驅動程序爲進程分配的內核緩衝區的大小保存在成員變量buffer_size中。這些內核緩衝區有兩個地址,其中一個是內核空間地址,另一個是用戶空間地址。內核空間地址是在Binder驅動程序內部使用的,保存在成員變量buffer中,而用戶空間地址是在應用程序進程內部使用的,保存在成員變量vma中。這兩個地址相差一個固定的值,保存在成員變量user_buffer_offset中。這樣,給定一個用戶空間地址或者一個內核空間地址,Binder驅動程序就能夠計算出另一個地址的大小。函數
注意:這兩個地址指的都是虛擬地址,它們對應的物理頁面保存在成員變量pages中。成員變量pages是類型爲struct page*的一個數組,數組中的每個元素都指向一個物理頁面。Binder驅動程序一開始時只爲該內核緩衝區分配一個物理頁面,後面不夠使用時,再繼續分配。
-------------------------------------------
buffers , allocated_buffers,free_buffers,buffer_free,free_async_space : 成員變量buffer指向的是一塊大的內核緩衝區,Binder驅動程序爲了方便對它進行管理,會將它劃分紅若干個小塊。這些小塊的內核緩衝區就是使用結構體binder_buffer來描述,它們保存在一個列表中,按照地址值從小到大的順序來排列。成員變量buffers指向的即是該列表的頭部。列表中的小塊內核緩衝區有的是正在使用的,即已經分配了物理頁面;有的是空閒的,即尚未分配物理頁面,它們分別組織在兩個紅黑樹中,其中,前者保存在成員變量allocated_buffers所描述的紅黑樹中,然後者保存在成員變量free_buffers所描述的紅黑樹中。此外,成員變量buffer_free保存了空閒內核緩衝區的大小,而成員變量free_async_space保存了當前能夠用來保存異步事務數據的內核緩衝區的大小。
-------------------------------------------
threads, max_threads,ready_threads,requested_threads,requested_threads_started : 每個使用了Binder進程間通訊機制的進程都有一個Binder線程池,用來處理進程間通訊請求,這個Binder線程池是由Binder驅動程序來維護的。結構體binder_proc的成員變量threads是一個紅黑樹的根節點,它以線程ID做爲關鍵字來組織一個進程的Binder線程池。進程能夠調用函數ioctl將一個線程註冊到Binder驅動程序中,同時,當進程沒有足夠的空閒線程在處理進程間通訊請求時,Binder驅動程序也能夠主動要求進程註冊更多的線程到Binder線程池中。Binder驅動程序最多能夠主動請求進程註冊的線程的數量保存在成員變量max_threads中,而成員變量ready_threads表示進程當前的空閒Binder線程數目。
注意:成員變量max_threads並非表示Binder線程池中的最大線程數目,進程自己能夠主動註冊任意數目的線程到Binder線程池中。Binder驅動程序每一次主動請求進程註冊一個線程時,都會將成員變量requested_threads的值加1;而當進程響應這個請求以後,Binder驅動程序就會將成員變量requested_threads的值減1,並且將成員變量requested_threads_started的值加1,表示Binder驅動程序已經主動請求進程註冊了多少個線程到Binder線程池中。
-------------------------------------------
todo :當進程接收到一個進程間通訊請求時,Binder驅動程序就將該請求封裝成一個工做項,而且加入到進程的待處理工做項隊列中,這個隊列使用成員變量todo來描述。
wait :Binder線程池中的空閒Binder線程會睡眠在由成員變量wait所描述的一個等待隊列中,當它們的宿主進程的待處理工做項隊列增長了新的工做項以後,Binder驅動程序就會喚醒這些線程,以便它們能夠去處理新的工做項。
---------------------------------------------
nodes ,refs_by_desc, refs_by_node :一個進程內部包含了一系列的Binder實體對象(結構體binder_node)和Binder引用對象(結構體binder_ref),進程使用三個紅黑樹來組織它們,其中,成員變量nodes所描述的紅黑樹是用來組織Binder實體對象的,它以Binder實體對象的成員變量ptr做爲關鍵字;而成員變量refs_by_desc和refs_by_node所描述的紅黑樹是用來組織Binder引用對象的,前者以Binder引用對象的成員變量desc做爲關鍵字,然後者以Binder引用對象的成員變量node做爲關鍵字。
---------------------------------------------
成員變量deferred_work_node是一個hash列表,用來保存進程能夠延遲執行的工做項。這些延遲工做項有三種類型,見:binder_deferred_state。若是一個進程有延遲執行的工做項,那麼成員變量deferred_work_node就恰好是該hash列表中的一個節點,而且使用成員變量deferred_work來描述該延遲工做項的具體類型。
struct binder_proc { struct hlist_node proc_node; struct rb_root threads; struct rb_root nodes; struct rb_root refs_by_desc; struct rb_root refs_by_node; int pid; struct vm_area_struct *vma; struct mm_struct *vma_vm_mm; struct task_struct *tsk; struct files_struct *files; struct hlist_node deferred_work_node; int deferred_work; void *buffer; ptrdiff_t user_buffer_offset; struct list_head buffers; struct rb_root free_buffers; struct rb_root allocated_buffers; size_t free_async_space; struct page **pages; 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; int requested_threads; int requested_threads_started; int ready_threads; long default_priority; struct dentry *debugfs_entry; };
enum binder_deferred_state { BINDER_DEFERRED_PUT_FILES = 0x01, BINDER_DEFERRED_FLUSH = 0x02, BINDER_DEFERRED_RELEASE = 0x04, };
Binder驅動程序爲進程分配內核緩衝區時,會爲這個內核緩衝區建立一個文件描述符,進程能夠經過這個文件描述符將該內核緩衝區映射到本身的地址空間。當進程再也不須要使用Binder進程間通訊機制時,它就會通知Binder驅動程序關閉該文件描述符,而且釋放以前所分配的內核緩衝區。因爲這不是一個立刻就須要完成的操做,所以,Binder驅動程序就會建立一個BINDER_DEFERRED_PUT_FILES類型的工做項來延遲執行該操做。
前面提到,Binder線程池中的空閒Binder線程是睡眠在一個等待隊列中的,進程能夠經過調用函數flush來喚醒這些線程,以便它們能夠檢查進程是否有新的工做項須要處理。這時候Binder驅動程序就會建立一個BINDER_DEFERRED_FLUSH類型的工做項,以即可以延遲執行喚醒空閒Binder線程的操做。
當進程再也不使用Binder進程間通訊機制時,它就會調用函數close來關閉設備文件/dev/binder,這時候Binder驅動程序就會釋放以前爲它分配的資源,例如,釋放進程結構體binder_proc、Binder實體對象結構體binder_node以及Binder引用對象結構體binder_ref等。因爲資源的釋放操做是一個比較耗時的操做,所以,Binder驅動程序會建立一個BINDER_DEFERRED_RELEASE類型的事務來延遲執行它們。
結構體binder_buffer用來描述一個內核緩衝區,它是用來在進程間傳輸數據的。
entry :每個使用Binder進程間通訊機制的進程在Binder驅動程序中都有一個內核緩衝區列表,用來保存Binder驅動程序爲它所分配的內核緩衝區,而成員變量entry正好是這個內核緩衝區列表的一個節點。
free , rb_node : 進程又使用了兩個紅黑樹來分別保存那些正在使用的內核緩衝區,以及空閒的內核緩衝區。若是一個內核緩衝區是空閒的,即它的成員變量free的值等於1,那麼成員變量rb_node就是空閒內核緩衝區紅黑樹中的一個節點;不然,成員變量rb_node就是正在使用內核緩衝區紅黑樹中的一個節點。
transaction , target_node : 成員變量transaction 和 target_node用來描述一個內核緩衝區正在交給哪個事務以及哪個Binder實體對象使用。
allow_user_free :是否容許釋放緩衝區,見下文
async_transaction :若是與一個內核緩衝區關聯的是一個異步事務,那麼Binder驅動程序就會將該內核緩衝區的成員變量async_transaction的值設置爲1;不然,就將它的值設置爲0。Binder驅動程序限制了分配給異步事務的內核緩衝區的大小,這樣作的目的是爲了保證同步事務能夠優先獲得內核緩衝區,以即可以快速地對該同步事務進行處理。
data , offsets_size , data_size : 成員變量data指向一塊大小可變的數據緩衝區,它是真正用來保存通訊數據的。數據緩衝區保存的數據劃分爲兩種類型,其中一種是普通數據,另外一種是Binder對象。Binder驅動程序不關心數據緩衝區中的普通數據,可是必需要知道里面的Binder對象,由於它須要根據它們來維護內核中的Binder實體對象和Binder引用對象的生命週期。例如,若是數據緩衝區中包含了一個Binder引用,而且該數據緩衝區是傳遞給另一個進程的,那麼Binder驅動程序就須要爲另一個進程建立一個Binder引用對象,而且增長相應的Binder實體對象的引用計數,由於它也被另外的這個進程引用了。因爲數據緩衝區中的普通數據和Binder對象是混合在一塊兒保存的,它們之間並無固定的順序,所以,Binder驅動程序就須要額外的數據來找到裏面的Binder對象。在數據緩衝區的後面,有一個偏移數組,它記錄了數據緩衝區中每個Binder對象在數據緩衝區中的位置。偏移數組的大小保存在成員變量offsets_size中,而數據緩衝區的大小保存在成員變量data_size中。
debug_id : 最後,成員變量debug_id用來標誌一個內核緩衝區的身份,它是用來幫助調試Binder驅動程序的。
struct binder_buffer { struct list_head entry; /* free and allocated entries by address */ struct rb_node rb_node; /* free entry by size or allocated entry */ /* by address */ unsigned free:1; unsigned allow_user_free:1; unsigned async_transaction:1; unsigned debug_id:29; struct binder_transaction *transaction; struct binder_node *target_node; size_t data_size; size_t offsets_size; uint8_t data[0]; };
Binder驅動程序使用一個binder_transaction結構體來描述一個事務,每個事務都關聯有一個目標Binder實體對象。Binder驅動程序將事務數據保存在一個內核緩衝區中,而後將它交給目標Binder實體對象處理,而目標Binder實體對象再將該內核緩衝區的內容交給相應的Service組件處理。Service組件處理完成該事務以後,若是發現傳遞給它的內核緩衝區的成員變量allow_user_free的值爲1,那麼該Service組件就會請求Binder驅動程序釋放該內核緩衝區。
從server進程和client進程傳遞給binder驅動程序的命令碼:
enum binder_driver_command_protocol { BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), BC_REPLY = _IOW('c', 1, struct binder_transaction_data), /* * binder_transaction_data: the sent command. */ BC_ACQUIRE_RESULT = _IOW('c', 2, __s32), /* * not currently supported * int: 0 if the last BR_ATTEMPT_ACQUIRE was not successful. * Else you have acquired a primary reference on the object. */ BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t), /* * void *: ptr to transaction data received on a read */ BC_INCREFS = _IOW('c', 4, __u32), BC_ACQUIRE = _IOW('c', 5, __u32), BC_RELEASE = _IOW('c', 6, __u32), BC_DECREFS = _IOW('c', 7, __u32), /* * int: descriptor */ BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie), BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie), /* * void *: ptr to binder * void *: cookie for binder */ BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc), /* * not currently supported * int: priority * int: descriptor */ BC_REGISTER_LOOPER = _IO('c', 11), /* * No parameters. * Register a spawned looper thread with the device. */ BC_ENTER_LOOPER = _IO('c', 12), BC_EXIT_LOOPER = _IO('c', 13), /* * No parameters. * These two commands are sent as an application-level thread * enters and exits the binder loop, respectively. They are * used so the binder can have an accurate count of the number * of looping threads it has available. */ BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_handle_cookie), /* * int: handle * void *: cookie */ BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_handle_cookie), /* * int: handle * void *: cookie */ BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t), /* * void *: cookie */ };
BC_TRANSACTION ,BC_REPLY : 命令協議代碼BC_TRANSACTION和BC_REPLY後面跟的通訊數據使用一個結構體binder_transaction_data來描述。當一個進程請求另一個進程執行某一個操做時,源進程就使用命令協議代碼BC_TRANSACTION來請求Binder驅動程序將通訊數據傳遞到目標進程;當目標進程處理完成源進程所請求的操做以後,它就使用命令協議代碼BC_REPLY來請求Binder驅動程序將結果數據傳遞給源進程。
BC_FREE_BUFFER : 命令協議代碼BC_FREE_BUFFER後面跟的通訊數據是一個整數,它指向了在Binder驅動程序內部所分配的一塊內核緩衝區。Binder驅動程序經過內核緩衝區將源進程的通訊數據傳遞到目標進程的。當目標進程處理完成源進程的通訊請求以後,它就會使用命令協議代碼BC_FREE_BUFFER來通知Binder驅動程序釋放這個內核緩衝區。
BC_INCREFS、BC_ACQUIRE、BC_RELEASE和BC_DECREFS : 通訊數據是一個整數,它描述了一個Binder引用對象的句柄值,其中,命令協議代碼BC_INCREFS和BC_DECREFS分別用來增長和減小一個Binder引用對象的弱引用計數;而命令協議代碼BC_ACQUIRE和BC_RELEASE分別用來增長和減小一個Binder引用對象的強引用計數。
BC_INCREFS_DONE和BC_ACQUIRE_DONE :命令協議代碼BC_INCREFS_DONE和BC_ACQUIRE_DONE後面跟的通訊數據使用一個結構體binder_ptr_cookie來描述。Binder驅動程序第一次增長一個Binder實體對象的強引用計數或者弱引用計數時,就會使用返回協議代碼BR_ACQUIRE或者BR_INCREFS來請求對應的Server進程增長對應的Service組件的強引用計數或者弱引用計數。當Server進程處理完成這兩個請求以後,就會分別使用命令協議代碼BC_INCREFS_DONE和BC_ACQUIRE_DONE將操做結果返回給Binder驅動程序。
命令協議代碼BC_REGISTER_LOOPER、BC_ENTER_LOOPER和BC_EXIT_LOOPER後面不須要指定通訊數據。一方面,當一個線程將本身註冊到Binder驅動程序以後,它接着就會使用命令協議代碼BC_ENTER_LOOPER來通知Binder驅動程序,它已經準備就緒處理進程間通訊請求了;另外一方面,當Binder驅動程序主動請求進程註冊一個新的線程到它的Binder線程池中來處理進程間通訊請求以後,新建立的線程就會使用命令協議代碼BC_REGISTER_LOOPER來通知Binder驅動程序,它準備就緒了。最後,當一個線程要退出時,它就使用命令協議代碼BC_EXIT_LOOPER從Binder驅動程序中註銷,這樣它就不會再接收到進程間通訊請求了。
命令協議代碼BC_REQUEST_DEATH_NOTIFICATION和BC_CLEAR_DEATH_NOTIFICATION後面跟的通訊數據使用一個結構體binder_ptr_cookie來描述。一方面,若是一個進程但願得到它所引用的Service組件的死亡接收通知,那麼它就須要使用命令協議代碼BC_REQUEST_DEATH_NOTIFICATION來向Binder驅動程序註冊一個死亡接收通知;另外一方面,若是一個進程想註銷以前所註冊的一個死亡接收通知,那麼它就須要使用命令協議代碼BC_CLEAR_DEATH_NOTIFICATION來向Binder驅動程序發出請求。
命令協議代碼BC_DEAD_BINDER_DONE後面跟的通訊數據是一個void類型的指針,指向一個死亡接收通知結構體binder_ref_death的地址。當一個進程得到一個Service組件的死亡通知時,它就會使用命令協議代碼BC_DEAD_BINDER_DONE來通知Binder驅動程序,它已經處理完成該Service組件的死亡通知了。
從binder驅動程序傳遞給server進程和client進程的命令碼:
enum binder_driver_return_protocol { BR_ERROR = _IOR('r', 0, __s32), /* * int: error code */ BR_OK = _IO('r', 1), /* No parameters! */ BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data), BR_REPLY = _IOR('r', 3, struct binder_transaction_data), /* * binder_transaction_data: the received command. */ BR_ACQUIRE_RESULT = _IOR('r', 4, __s32), /* * not currently supported * int: 0 if the last bcATTEMPT_ACQUIRE was not successful. * Else the remote object has acquired a primary reference. */ BR_DEAD_REPLY = _IO('r', 5), /* * The target of the last transaction (either a bcTRANSACTION or * a bcATTEMPT_ACQUIRE) is no longer with us. No parameters. */ BR_TRANSACTION_COMPLETE = _IO('r', 6), /* * No parameters... always refers to the last transaction requested * (including replies). Note that this will be sent even for * asynchronous transactions. */ BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie), BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie), BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie), BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie), /* * void *: ptr to binder * void *: cookie for binder */ BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie), /* * not currently supported * int: priority * void *: ptr to binder * void *: cookie for binder */ BR_NOOP = _IO('r', 12), /* * No parameters. Do nothing and examine the next command. It exists * primarily so that we can replace it with a BR_SPAWN_LOOPER command. */ BR_SPAWN_LOOPER = _IO('r', 13), /* * No parameters. The driver has determined that a process has no * threads waiting to service incoming transactions. When a process * receives this command, it must spawn a new service thread and * register it via bcENTER_LOOPER. */ BR_FINISHED = _IO('r', 14), /* * not currently supported * stop threadpool thread */ BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t), /* * void *: cookie */ BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t), /* * void *: cookie */ BR_FAILED_REPLY = _IO('r', 17), /* * The the last transaction (either a bcTRANSACTION or * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters. */ };
BR_ERROR : 返回協議代碼BR_ERROR後面跟的通訊數據是一個整數,用來描述一個錯誤代碼。Binder驅動程序在處理應用程序進程發出的某個請求時,若是發生了異常狀況,它就會使用返回協議代碼BR_ERROR來通知應用程序進程。
BR_OK :返回協議代碼BR_OK後面不須要指定通訊數據。Binder驅動程序成功處理了應用程序進程發出的某一個請求以後,它就會使用返回協議代碼BR_OK來通知應用程序進程。
BR_TRANSACTION,BR_REPLY :返回協議代碼BR_TRANSACTION和BR_REPLY後面跟的通訊數據使用一個結構體binder_transaction_data來描述。當一個Client進程向一個Server進程發出進程間通訊請求時,Binder驅動程序就會使用返回協議代碼BR_TRANSACTION通知該Server進程來處理該進程間通訊請求;當Server進程處理完成該進程間通訊請求以後,Binder驅動程序就會使用返回協議代碼BR_REPLY將進程間通訊請求結果數據返回給Client進程。
BR_DEAD_REPLY :返回協議代碼BR_DEAD_REPLY後面不須要指定通訊數據。Binder驅動程序在處理進程間通訊請求時,若是發現目標進程或者目標線程已經死亡,它就會使用返回協議代碼BR_DEAD_REPLY來通知源進程。
BR_TRANSACTION_COMPLETE :返回協議代碼BR_TRANSACTION_COMPLETE後面不須要指定通訊數據。當Binder驅動程序接收到應用程序進程給它發送的一個命令協議代碼BC_TRANSACTION或者BC_REPLY時,它就會使用返回協議代碼BR_TRANSACTION_COMPLETE來通知應用程序進程,該命令協議代碼已經被接收,正在分發給目標進程或者目標線程處理。
BR_INCREFS、BR_ACQUIRE、BR_RELEASE和BR_DECREFS :返回協議代碼BR_INCREFS、BR_ACQUIRE、BR_RELEASE和BR_DECREFS後面跟的通訊數據使用一個結構體binder_ptr_cookie來描述,其中,命令協議代碼BR_INCREFS和BR_DECREFS分別用來增長和減小一個Service組件的弱引用計數;而命令協議代碼BR_ACQUIRE和BR_RELEASE分別用來增長和減小一個Service組件的強引用計數。
BR_NOOP :返回協議代碼BR_NOOP後面不須要指定通訊數據。Binder驅動程序使用返回協議代碼BR_NOOP來通知應用程序進程執行一個空操做,它的存在是爲了方便之後能夠替換爲返回協議代碼BR_SPAWN_LOOPER。
BR_SPAWN_LOOPER:返回協議代碼BR_SPAWN_LOOPER後面不須要指定通訊數據。當Binder驅動程序發現一個進程沒有足夠的空閒Binder線程來處理進程間通訊請求時,它就會使用返回協議代碼BR_SPAWN_LOOPER來通知該進程增長一個新的線程到Binder線程池中。
BR_DEAD_BINDER和BR_CLEAR_DEATH_NOTIFICATION_DONE :返回協議代碼BR_DEAD_BINDER和BR_CLEAR_DEATH_NOTIFICATION_DONE後面跟的通訊數據是一個void類型的指針,它指向一個用來接收Service組件死亡通知的對象的地址。當Binder驅動程序監測到一個Service組件的死亡事件時,它就會使用返回協議代碼BR_DEAD_BINDER來通知相應的Client進程。當Client進程通知Binder驅動程序註銷它以前所註冊的一個死亡接收通知時,Binder驅動程序執行完成這個註銷操做以後,就會使用返回協議代碼BR_CLEAR_DEATH_NOTIFICATION_DONE來通知Client進程。
BR_FAILED_REPLY :返回協議代碼BR_FAILED_REPLY後面不須要指定通訊數據。當Binder驅動程序處理一個進程發出的BC_TRANSACTION命令協議時,若是發生了異常狀況,它就會使用返回協議代碼BR_FAILED_REPLY來通知源進程。
struct binder_ptr_cookie { binder_uintptr_t ptr; binder_uintptr_t cookie; };
當結構體binder_ptr_cookie描述的是一個Binder實體對象時,成員變量ptr和cookie的含義等同於結構體binder_node的成員變量ptr和cookie,它們用來描述用戶空間中的一個Service組件,其中,成員變量cookie指向該Service組件的地址,而成員變量ptr指向該Service組件內部的一個引用計數對象(類型爲weakref_impl)的地址;
當結構體binder_ptr_cookie描述的是一個Service組件的死亡接收通知時,成員變量ptr指向的是一個Binder引用對象的句柄值,而成員變量cookie指向的是一個用來接收死亡通知的對象的地址。
結構體binder_transaction_data用來描述進程間通訊過程當中所傳輸的數據。
struct binder_transaction_data { /* The first two are only used for bcTRANSACTION and brTRANSACTION, * identifying the target and contents of the transaction. */ union { /* target descriptor of command transaction */ __u32 handle; /* target descriptor of return transaction */ binder_uintptr_t ptr; } target; binder_uintptr_t cookie; /* target object cookie */ __u32 code; /* transaction command */ /* General information about the transaction. */ __u32 flags; pid_t sender_pid; uid_t sender_euid; binder_size_t data_size; /* number of bytes of data */ binder_size_t offsets_size; /* number of bytes of offsets */ /* If this transaction is inline, the data immediately * follows here; otherwise, it ends with a pointer to * the data buffer. */ union { struct { /* transaction data */ binder_uintptr_t buffer; /* offsets from buffer to flat_binder_object structs */ binder_uintptr_t offsets; } ptr; __u8 buf[8]; } data; };
target : 成員變量target是一個聯合體,用來描述一個目標Binder實體對象或者目標Binder引用對象。若是它描述的是一個目標Binder實體對象,那麼它的成員變量ptr就指向與該Binder實體對象對應的一個Service組件內部的一個弱引用計數對象(weakref_impl)的地址;若是它描述的是一個目標Binder引用對象,那麼它的成員變量handle就指向該Binder引用對象的句柄值。
cookie : 當Binder驅動程序使用返回命令協議BR_TRANSACTION向一個Server進程發出一個進程間通訊請求時,cookie成員變量纔有實際意義,它指向的是目標Service組件的地址。
code : 成員變量code是由執行進程間通訊的兩個進程互相約定好的一個通訊代碼,Binder驅動程序徹底不關心它的含義。
成員變量flags是一個標誌值,用來描述進程間通訊行爲特徵,它的取值以下所示
enum transaction_flags { TF_ONE_WAY = 0x01, /* this is a one-way call: async, no return */ TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */ TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */ TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */ };
目前,只使用了TF_ONE_WAY、TF_STATUS_CODE和TF_ACCEPT_FDS這三個標誌值。若是成員變量flags的TF_ONE_WAY位被設置爲1,就表示這是一個異步的進程間通訊過程;若是成員變量flags的TF_ACCEPT_FDS位被設置爲0,就表示源進程不容許目標進程返回的結果數據中包含有文件描述符;若是成員變量flags的TF_STATUS_CODE位被設置爲1,就表示成員變量data所描述的數據緩衝區的內容是一個4字節的狀態碼。
sender_pid和sender_euid : 成員變量sender_pid和sender_euid表示發起進程間通訊請求的進程的PID和UID。這兩個成員變量的值是由Binder驅動程序來填寫的,所以,目標進程經過這兩個成員變量就能夠識別出源進程的身份,以便進行安全檢查。
成員變量data_size和offsets_size分別用來描述一個通訊數據緩衝區以及一個偏移數組的大小。成員變量data是一個聯合體,它指向一個通訊數據緩衝區。當通訊數據較小時,就直接使用聯合體內靜態分配的數組buf來傳輸數據;當通訊數據較大時,就須要使用一塊動態分配的緩衝區來傳輸數據了。這塊動態分配的緩衝區經過一個包含兩個指針的結構體來描述,即經過聯合體內的成員變量ptr來描述。結構體ptr的成員變量buffer指向一個數據緩衝區,它是真正用來保存通訊數據的,它的大小由前面所描述的成員變量data_size來指定。當數據緩衝區中包含有Binder對象時,那麼緊跟在這個數據緩衝區的後面就會有一個偏移數組offsets,用來描述數據緩衝區中每個Binder對象的位置。有了這個偏移數組以後,Binder驅動程序就能夠正確地維護其內部的Binder實體對象和Binder引用對象的引用計數。
數據緩衝區中的每個Binder對象都使用一個flat_binder_object結構體來描述。
好比上面,data.ptr.buffer指向一塊data_size大小的空間,包含兩個binder對象,offset值分別是n1和n2。
用來描述binder_transaction_data中傳輸數據是用到的binder對象,可使Binder引用對象,或者binder實體對象,也能夠是一個文件描述符,它們是經過成員變量type來加以區別的。
#define B_PACK_CHARS(c1, c2, c3, c4) \ ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4)) #define B_TYPE_LARGE 0x85 enum { BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE), BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE), BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE), BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE), BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE), }; struct flat_binder_object { /* 8 bytes for large_flat_header. */ __u32 type; __u32 flags; /* 8 bytes of data. */ union { binder_uintptr_t binder; /* local object */ __u32 handle; /* remote object */ }; /* extra data associated with local object */ binder_uintptr_t cookie; };
BINDER_TYPE_BINDER和BINDER_TYPE_WEAK_BINDER都是用來描述一個Binder實體對象的,前者描述的是一個強類型的Binder實體對象,然後者描述的是一個弱類型的Binder實體對象。
BINDER_TYPE_HANDLE和BINDER_TYPE_WEAK_HANDLE用來描述一個Binder引用對象,前者描述的是一個強類型的Binder引用對象,然後者描述的是一個弱類型的Binder引用對象 。
BINDER_TYPE_FD用來描述一個文件描述符。
成員變量flags是一個標誌值,只有當結構體flat_binder_object描述的是一個Binder實體對象時,它纔有實際意義。目前只用到該成員變量的第0位到第8位。其中,第0位到第7位描述的是一個Binder實體對象在處理一個進程間通訊請求時,它所運行在的線程應當具備的最小線程優先級;第8位用來描述一個Binder實體對象是否能夠將一塊包含有文件描述符的數據緩衝區傳輸給目標進程,若是它的值等於1,就表示容許,不然就不容許。
成員變量binder和handle組成了一個聯合體。當結構體flat_binder_object描述的是一個Binder實體對象時,那麼就使用成員變量binder來指向與該Binder實體對象對應的一個Service組件內部的一個弱引用計數對象(weakref_impl)的地址,而且使用成員變量cookie來指向該Service組件的地址;當結構體flat_binder_object描述的是一個Binder引用對象時,那麼就使用成員變量handle來描述該Binder引用對象的句柄值。