一、Binder機制概述
在Android開發中,很多時候我們需要用到進程間通信,所謂進程間通信,實現進程間通信的機制有很多種,比如說socket、pipe等,Android中進程間通信的方式主要有三種:
1.標准Linux Kernel IPC 接口;
2.標准D-BUS接口;
3.Binder接口。
其中,Binder機制是使用最且最被認可的,因為Binder機制有以下優點:
1.相對於其它IPC機制,Binder機制更加簡潔和快速;
2.消耗的內存相對更少;
3.傳統的IPC機制可能會增加進程的開銷,以及出現進程過載和安全漏洞,Binder機制則有效避免和解決了這些問題。
Binder機制是Android系統的核心機制,幾乎貫穿於整個Android系統,Android系統基本上可以看作是一個基於binder通信機制的C/S架構,Binder就像網絡,把Android系統的各個部分連接到了一起。利用Binder機制,可以實現以下功能:
1.用驅動程序來推進進程間通信;
2.通過共享內存來提高性能;
3.為進程請求分配每個進程的線程池;
4.針對系統中的對象引入了引用計數和跨進程的對象引用映射;
5.進程間同步調用。
二、Binder機制的工作流程
1.客戶端獲取服務端的帶來對象(proxy)。我們需要明確的是客戶端進程並不能直接操作服務端中的方法,如果要操作服務端中的方法,那麼有一個可行的解決方法就是在客戶端建立一個服務端進程的代理對象,這個代理對象具備和服務端進程一樣的功能,要訪問服務端進程中的某個方法,只需要訪問代理對象中對應的方法即可;
2.客戶端通過調用代理對象向服務端發送請求。
3.代理對象將用戶請求通過Binder驅動發送到服務器進程;
4.服務端進程處理客戶端發過來的請求,處理完之後通過Binder驅動返回處理結果給客戶端的服務端代理對象;
5.代理對象將請求結果進一步返回給客戶端進程。
通過以上5個步驟,就完成了一次Binder通信。
三、Binder機制的組成
Binder機制由三部分組成,即:
1.Client;
2.Server;
3.ServiceManager。
三部分組件之間的關系:
1.Client、Server、ServiceManager均在用戶空間中實現,而Binder驅動程序則是在內核空間中實現的;
2.在Binder通信中,Server進程先注冊一些Service到ServiceManager中,ServiceManager負責管理這些Service並向Client提供相關的接口;
3.Client進程要和某一個具體的Service通信,必須先從ServiceManager中獲取該Service的相關信息,Client根據得到的Service信息與Service所在的Server進程建立通信,之後Clent就可以與Service進行交互了;
4.Binder驅動程序提供設備文件/dev/binder與用戶空間進行交互,Client、Server和ServiceManager通過open和ioctl文件操作函數與Binder驅動程序進行通信;
5.Client、Server、ServiceManager三者之間的交互都是基於Binder通信的,所以通過任意兩者這件的關系,都可以解釋Binder的機制。
四、Binder驅動的實現簡介。
1.Binder采用了AIDL來描述進程間的接口;
2.Binder是一個特殊的字符型設備,設備節點為dev/binder。
3.Binder驅動程序由以下兩個文件實現:
①kernel/drivers/staging/binder.h
②kernel/drivers/staging/binder.c
4.在Binder驅動的實現過程中,以下函數起著關鍵作用:
①使用binder_ioctl()函數與用戶空間交換數據;
②BINDER_WRITE_READ用來讀寫數據,數據包中的cmd域用於區分不同的請求;
③使用binder_thread_write()函數來發送請求或返回結果,在binder_thread_write()函數中,通過調用binder_transaction()函數來轉發請求並返回結果.當收到請求時,binder_transaction()函數會通過對象的handle找到對象所在的進程,如果handle結果為空,則認為此對象是context_mgr,然後把請求發給context_mgr所在的進程,並將請求中所有的Binder對象放到RB樹中,最後把請求放到目標進程的隊列中以等待目標進程的讀取。;
④使用binder_thread_read()函數來讀取結果;
⑤在函數binder_parse()中實現數據解析工作。
五、Binder驅動程序中的數據結構
1.binder_work。binder_work表示在binder驅動中進程要處理的工作項。
2.binder_node。binder_node用於定義Binder實體對象。Android系統中每一個Srevice組件在Binder驅動程序中都對應一個Binder實體對象。驅動中的Binder實體也叫做“節點”,你屬於提供實體的進程;
3.binder_ref。binder_ref用於描述一個Binder引用對象。Android系統中每一個Client組件在Binder驅動程序中都對應一個Binder引用對象;
4.binder_ref_death。binder_ref_death是一個通知結構體。只要某進程訂閱了某binder引用對應實體的死亡通知,那麼binder驅動就會為該binder引用建立一個binder_ref_death通知結構體,將其保存在當前進程的對應binder引用結構體的death域中,即Binder引用對象將死亡通知注冊到Binder驅動程序中。這裡涉及到Binder的死亡通知機制,Binder的死亡通知機制具體指:如果Binder實體對象意外死亡,那麼將會導致改Binder實體對象的引用變得無效,因而就需要在Binder實體對象死亡的時候通知到所有引用它的代理對象,從而在一定程度上預防和解決Binder飲用對象無效的問題;
5.binder_buffer。Binder_Buffer用於描述一個內核緩沖區,能夠在進程之間傳輸數據;
6.binder_proc。binder_proc表示正在使用Binder進程通信機制的進程,能夠保存調用Binder的各個進程或線程的信息,如線程ID、進程ID、Binder狀態信息等;
7.binder_thread。binder_thread用於存儲每一個單獨的線程的信息,表示Binder線程池中的一個線程;
8.binder_transaction。binder_transaction用於中轉請求和返回結果,並保存接收和要發送的進程信息;
9.binder_write_read。binder_write_read表示在進程之間的通信過程中傳輸的數據,數據包中有一個cmd域用於區分不同的請求;
10.BinderDriverCommandProtocol。結構體binder_write_read包含的命令在BinderDriverCommandProtocol中定義;
11.BinderDriverReturnProtocol。BinderDriverReturnProtocol中定義了讀操作命令協議;
12.binder_ptr_cookie。binder_ptr_cookie表示一個Binder實體對象或Service組件的死亡接收通知;
13.binder_transaction_data。binder_transaction_data表示在通信過程中傳遞的數據;
14.flat_binder_object。flat_binder_object表示Binder對象。Android系統中,在進程之間傳遞的數據稱為Binder對象。
六、Binder的詳細實現。
1.設備初始化。Binder機制的設備初始化函數binder_init位於inder.c中,在進行設備初始化的時候binder_init會調用設備驅動接口函數device_initcall;
2.打開設備文件。Binder機制,函數binder_open用於打開Binder設備文件/dev/binder。Android系統中,驅動程序的任何一個進程及線程都可以打開一個Binder設備;與binder_open函數功能相反的是binder_release函數,用於釋放打開的空間以及操作過程中分配的空間;
3.實現內存映射。當打開Binder設備文件/dev/binder之後,需要調用函數mmap()把設備內存映射到用戶進程地址空間中,這樣就可以像操作用戶內存那樣操作設備內存。在Binder設備中,對內存的映射操作是有限制的,如Binder不能映射具有寫權限的內存區域,最大能映射4MB的內存區域等;
4.釋放物理頁面。Binder機制中,函數binder_insert_free_buffer()用於將進程中的Buffer插入進程信息中,即將一個空閒內核緩沖區加入進程中的空閒內核緩沖區的紅黑樹中;
5.處理內核緩沖區:
①*binder_alloc_buf()用於分配內核緩沖區;
②binder_insert_allocated_buffer()用於將分配的內核緩沖區添加到目標進程的已分配物理頁面的內核緩沖區紅黑樹中;
③binder_free_buf()用於釋放內核緩沖區的操作;
④*buffer_start_page()和*buffer_end_page()用於計算結構體binder_buffer所占用的虛擬頁面的地址;
⑤binder_delete_free_buffer()用於刪除結構體binder_buffer;
⑥*binder_buffer_lookup()根據一個用戶空間地址查詢一個內核緩沖區。
七、Binder封裝庫
Android源碼中,各個層次都有Binder的相關實現,其中主要由本地原生代碼實現,其它層次的Binder實現都是調用原生Binder庫來實現的。
Binder的各層次實現為:
1.Binder驅動部分。實現功能如下:
①組織Binder的服務及诶到哪;
②調用Binder相關的處理線程;
③完成實際的Binder傳輸。
2.Binder Adapter層。Binder Adapter層是對Binder驅動的封裝,主要功能是操作Binder驅動,因而應用程序無須直接和Binder驅動程序關聯。關聯文件包括IPCThreadState.cpp、ProcessState.cpp和Parcel.cpp中的一些內容。Binder核心庫是Binder框架的核心實現,主要包括IBinder、Binder(服務端)和BpBinder(客戶端)。
3.頂層。頂層binder框架和具體的客戶端。
三層結構如圖:
更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11