1. Binder內存機制
首先我(wo)們來(lai)看下安卓應用(yong)進程(cheng)在(zai)內存中的分(fen)布,如下圖所示:

每(mei)個(ge)Android進(jin)(jin)(jin)程(cheng)(cheng),只能運行(xing)(xing)在自己(ji)的(de)進(jin)(jin)(jin)程(cheng)(cheng)所擁有(you)的(de)虛擬地址空(kong)(kong)間(jian)(jian)(jian)(jian),如果是(shi)32位的(de)系統(tong),對應(ying)一(yi)(yi)(yi)個(ge)4GB的(de)虛擬地址空(kong)(kong)間(jian)(jian)(jian)(jian),其中3GB是(shi)用(yong)戶空(kong)(kong),1GB是(shi)內(nei)核(he)(he)(he)空(kong)(kong)間(jian)(jian)(jian)(jian),而內(nei)核(he)(he)(he)空(kong)(kong)間(jian)(jian)(jian)(jian)的(de)大小是(shi)可(ke)(ke)(ke)(ke)以(yi)(yi)通(tong)過參數配置的(de)。對于(yu)用(yong)戶空(kong)(kong)間(jian)(jian)(jian)(jian),不(bu)同進(jin)(jin)(jin)程(cheng)(cheng)之間(jian)(jian)(jian)(jian)彼此是(shi)不(bu)能共(gong)(gong)享的(de),而內(nei)核(he)(he)(he)空(kong)(kong)間(jian)(jian)(jian)(jian)確(que)實可(ke)(ke)(ke)(ke)以(yi)(yi)共(gong)(gong)享的(de)。Client進(jin)(jin)(jin)程(cheng)(cheng)與Server進(jin)(jin)(jin)程(cheng)(cheng)通(tong)信(xin),恰恰是(shi)利用(yong)進(jin)(jin)(jin)程(cheng)(cheng)間(jian)(jian)(jian)(jian)可(ke)(ke)(ke)(ke)共(gong)(gong)享的(de)內(nei)核(he)(he)(he)內(nei)空(kong)(kong)間(jian)(jian)(jian)(jian)來完(wan)成底層通(tong)信(xin)工作的(de),Client端(duan)與Server端(duan)進(jin)(jin)(jin)程(cheng)(cheng)往(wang)(wang)往(wang)(wang)采用(yong)ioctl等方法跟內(nei)核(he)(he)(he)空(kong)(kong)間(jian)(jian)(jian)(jian)的(de)驅動進(jin)(jin)(jin)行(xing)(xing)。(Binder是(shi)Android系統(tong)提(ti)供的(de)一(yi)(yi)(yi)種IPC機制(zhi)。每(mei)個(ge)Android的(de)進(jin)(jin)(jin)程(cheng)(cheng),都可(ke)(ke)(ke)(ke)以(yi)(yi)有(you)一(yi)(yi)(yi)塊用(yong)戶空(kong)(kong)間(jian)(jian)(jian)(jian)和(he)內(nei)核(he)(he)(he)空(kong)(kong)間(jian)(jian)(jian)(jian)。用(yong)戶空(kong)(kong)間(jian)(jian)(jian)(jian)在不(bu)同進(jin)(jin)(jin)程(cheng)(cheng)間(jian)(jian)(jian)(jian)不(bu)能共(gong)(gong)享,內(nei)核(he)(he)(he)空(kong)(kong)間(jian)(jian)(jian)(jian)可(ke)(ke)(ke)(ke)以(yi)(yi)共(gong)(gong)享。Binder就是(shi)一(yi)(yi)(yi)個(ge)利用(yong)可(ke)(ke)(ke)(ke)以(yi)(yi)共(gong)(gong)享的(de)內(nei)核(he)(he)(he)空(kong)(kong)間(jian)(jian)(jian)(jian),完(wan)成高性能的(de)進(jin)(jin)(jin)程(cheng)(cheng)間(jian)(jian)(jian)(jian)通(tong)信(xin)的(de)方案(an)。)
2. 和傳統IPC機制相比,谷歌為什么采用Binder
1、傳統IPC:匿名管道(PIPE)、信號(signal)、有名管道(FIFO)
2、AT&T Unix:共享內存,信號量,消息隊列
3、BSD Unix:Socket
性能:目前Linux支持的IPC包括傳統的管道,System V IPC(包括消息隊列/共享內存/信號量)以及socket,但是只有socket支持Client/Server的通信方式,由于socket是一套通用當初網絡通信方式,其效率低下,且消耗比較大(socket建立連接過程和中斷連接過程都有一定的開銷),明顯在手機上不適合大面積使用socket。而消息隊列和管道采用"存儲-轉發" 方式,即數據先從發送方緩存區拷貝到內核開辟的緩存區中,然后再從內核緩存中拷貝到接收方緩存中,至少有兩次拷貝過程。共享內存雖然無需拷貝,但控制復雜,難以使用。
安全性:在安全性方面,Android作為一個開放式,擁有眾多開發者的平臺,應用程序的來源廣泛,確保智能終端的安全是非常重要的。終端用戶不希望從網上下載的程序在不知情的情況下偷窺隱私數據,連接無線網絡,長期操作底層設備導致電池很快耗盡的情況。傳統IPC沒有任何安全措施,完全依賴上層協議來去報。首先傳統IPC的接受方無法獲取對方進程可靠的UID/PID(用戶ID/進程ID),從而無法鑒別對方身份。Android為每個安裝好的應用程序分配了自己的UID,故進程的UID是鑒別進程的身份的重要標志。使用傳統IPC只能由用戶在數據包里填入UID/PID,但這樣不可靠,容易被惡意程序利用。可靠的身份標記只由IPC機制本身在內核中添加。其次傳統IPC訪問接入點是開放的,無法建立私有通道。比如命名管道、system V的鍵值,socket的ip地址或者文件名都是開放的,只要知道這些接入點的程序都可以對端建立連接,不管怎樣都無法阻止惡意程序通過接收方地址獲得連接。

相比于傳統的跨進程通信手段,通信雙方必須要處理線程同步,內存管理等問題,工作量大,而且問題多,就像我們前面介紹的傳統IPC 命名管道(FIFO) 信號量(semaphore) 消息隊列已經從Android中去掉了,同其他IPC相比,Socket是一種比較成熟的通信手段了,同步控制也很容易實現。Socket用于網絡通信非常合適,但是用于進程間通信就效率很低。
Android在架構上一直希望模糊進程的概念,取而代之以組件的概念。應用也不需要關心組件存放的位置、組件運行在那個進程中、組件的生命周期等問題。隨時隨地的,只要擁有Binder對象,就能使用組件的功能。Binder就像一張網,將整個系統的組件,跨進程和線程的組織在一起。
3. AIDL
/** Construct the stub at attach it to the interface. */
publicStub()
{
 this.attachInterface(this,DESCRIPTOR);
}
/**
* Cast an IBinder object into an android.content.pm.IPackageStatsObserver interface,
* generating a proxy if needed.
*/
public staticandroid.content.pm.IPackageStatsObserverasInterface(android.os.IBinder obj)
{
 if((obj==null)) {
   return null;
 }
  android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
  if(((iin!=null)&&(iininstanceofandroid.content.pm.IPackageStatsObserver))) {
   return((android.content.pm.IPackageStatsObserver)iin);
 }
 return newandroid.content.pm.IPackageStatsObserver.Stub.Proxy(obj);}4. Binder通信

| 概念 | 作用 | 
| Binder代理對象 | 類型為BpBinder,在用戶空間創建,且執行在Client進程中.會被Client進程中的其他對象引用,另外會引用Binder驅動程序中的Binder引用對象. | 
| Binder引用對象 | 類型為binder_ref,在Binder驅動程序中創建,被Binder代理對象引用. | 
| Binder實體對象 | 類型為binder_node,在Binder驅動程序中創建,被Binder引用對象所引用 | 
| Binder本地對象 | 類型為BBinder,在用戶空間中創建,且執行在Server進程中.會被Server進程中其他對象引用,還會被Binder實體對象引用. | 
一次Binder通信最大可以傳輸多大的數(shu)據

1MB-8KB的限制來源(yuan)于哪里呢?(PS:8k是兩個pagesize,一個pagesize是申請物理內存的最(zui)小單(dan)元)
#defineBINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)//這里的限制是1MB-4KB*2
ProcessState::ProcessState(constchar*driver)
{
if(mDriverFD>=0){
// mmap the binder, providing a chunk of virtual address space to receive transactions.
// 調用mmap接口向Binder驅動中申請內核空間的內存
        mVMStart=mmap(0,BINDER_VM_SIZE,PROT_READ,MAP_PRIVATE|MAP_NORESERVE,mDriverFD,0);
if(mVMStart==MAP_FAILED){
// *sigh*
ALOGE("Using %s failed: unable to mmap transaction memory.\n",mDriverName.c_str());
close(mDriverFD);
            mDriverFD=-1;
            mDriverName.clear();
}
}
}virtualvoidonZygoteInit()
{
        sp<ProcessState>proc=ProcessState::self();
ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }- 創建一個匿名共享內存(android.os.SharedMemory即android提供的匿名共享內存,一般使用android.os.MemoryFile,MemoryFile即是對SharedMemory的一個簡單封裝)
- 往這個共享內存中寫一個字符數據
- 將這個匿名共享內存的文件句柄(如FileDescriptor)通過binder機制傳遞給客戶端
- bindservice獲得服務端的binder對象
- 調用binder的接口獲得服務端匿名共享內存的文件句柄
- 通過文件句柄,直接訪問匿名共享內存中的數據,并打印出log。

