亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

Binder通信原理

2023-07-24 02:20:54
62
0

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)。)

Binder進程間通信效率高的最主要原因是Binder的內存機制:虛擬進程地址空間(用戶空間)和虛擬內核地址空間(內核空間)都映射到同一塊物理內存空間。當Client端與Server端發送數據時,Client(作為數據發送端)先從自己的進程空間把IPC通信數據copy_from_user拷貝到內核空間,而Server端(作為數據接收端)與內核共享數據,不再需要拷貝數據,而是通過內存地址空間的偏移量,即可獲悉內存地址,整個過程只發生一次內存拷貝。
而一般IPC的做法,需要Client端進程空間拷貝到內核空間,再由內核空間拷貝到Server進程空間,會發生兩次拷貝。對于進程和內核虛擬地址映射到同一個物理內存的操作是發生在數據接收端,而數據發送端還是需要將用戶態的數據復制到內核態。
 

2. 和傳統IPC機制相比,谷歌為什么采用Binder

我們先看下Linux中的IPC通信機制:
  • 1、傳統IPC:匿名管道(PIPE)、信號(signal)、有名管道(FIFO)
  • 2、AT&T Unix:共享內存,信號量,消息隊列
  • 3、BSD Unix:Socket
雖然Android繼承Linux內核,但是Linux與Android通信機制是不同的。Android中有大量的C/S(Client/Server)應用方式,這就要求Android內部提供IPC方法,而如果采用Linux所支持的進程通信方式有兩個問題:性能和安全性。那
  • 性能:目前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地址或者文件名都是開放的,只要知道這些接入點的程序都可以對端建立連接,不管怎樣都無法阻止惡意程序通過接收方地址獲得連接。
基于以上原因,Android需要建立一套新的IPC機制來滿足系統對通信方式,傳輸性能和安全性的要求,所以就有了Binder。Binder基于Client/Server通信模式,傳輸過程只需要一次拷貝,為發送發添加UID/PID身份,支持實名Binder也支持匿名Binder,安全性高。下圖為Binder通信過程示例:
 
  • 相比于傳統的跨進程通信手段,通信雙方必須要處理線程同步,內存管理等問題,工作量大,而且問題多,就像我們前面介紹的傳統IPC 命名管道(FIFO) 信號量(semaphore) 消息隊列已經從Android中去掉了,同其他IPC相比,Socket是一種比較成熟的通信手段了,同步控制也很容易實現。Socket用于網絡通信非常合適,但是用于進程間通信就效率很低。
  • Android在架構上一直希望模糊進程的概念,取而代之以組件的概念。應用也不需要關心組件存放的位置、組件運行在那個進程中、組件的生命周期等問題。隨時隨地的,只要擁有Binder對象,就能使用組件的功能。Binder就像一張網,將整個系統的組件,跨進程和線程的組織在一起。
Binder是整個系統的運行的中樞。Android在進程間傳遞數據使用共享內存的方式,這樣數據只需要復制一次就能從一個進程到達另一個進程了(一般IPC都需要兩步,第一步用戶進程復制到內核,第二步再從內核復制到服務進程。)
PS: 整個Android系統架構中,雖然大量采用了Binder機制作為IPC(進程間通信)方式,但是也存在部分其他的IPC方式,比如Zygote通信就是采用socket。
 

3. AIDL

aidl會自動生成一個繼承自Binder的Stub的抽象類(Stub實現自定義接口),重寫了onTransact方法,在onTransact中從data parcel對象中讀取參數,然后根據code調用對應接口方法,并在reply parcel對象中寫入返回結果;
同時也會自動生成一個Proxy的類(Proxy也實現自定義接口),該類持有傳入的IBinder對象,在對應的自定義接口方法中,調用IBinder的transact傳入方法對應的code,參數data parcel,以及返回值reply parcel;
Proxy是Client層用到的,Stub是Server層需要繼承實現的;
/** 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通信的交互示例圖:
Binder通信涉及的主要對象及其作用如下表所示:
概念
作用
Binder代理對象
類型為BpBinder,在用戶空間創建,且執行在Client進程中.會被Client進程中的其他對象引用,另外會引用Binder驅動程序中的Binder引用對象.
Binder引用對象
類型為binder_ref,在Binder驅動程序中創建,被Binder代理對象引用.
Binder實體對象
類型為binder_node,在Binder驅動程序中創建,被Binder引用對象所引用
Binder本地對象
類型為BBinder,在用戶空間中創建,且執行在Server進程中.會被Server進程中其他對象引用,還會被Binder實體對象引用.
 
不管是client還是server,跟binder驅動交互都是通過以下步驟:

一次Binder通信最大可以傳輸多大的數(shu)據

Binder調用有oneway-異步和非oneway-同步兩種類型。

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();
}
}
}
如果一個進程使用ProcessState這個類來初始化Binder服務,這個進程的Binder內核內存上限就是BINDER_VM_SIZE,也就是1MB-8KB。
virtualvoidonZygoteInit()
{
        sp<ProcessState>proc=ProcessState::self();
ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }
對于普通的APP來說,都是Zygote進程孵化出來的,Zygote進程的初始化Binder服務的時候提前調用了ProcessState這個類,所以普通的APP進程上限就是1MB-8KB。
但是我們可以通過手寫mmap繞過ProcessState的限制;Binder服務的初始化有兩步,open打開Binder驅動,mmap在Binder驅動中申請內核空間內存,所以我們只要手寫open,mmap就可以輕松突破這個限制。但是mmap中有判斷如果傳入申請的空間大于4M則會最多只申請4M;
但是為什么ContentProvider卻能傳輸超過4M或更大的數據呢,其實用的是匿名共享內存;
服務端需做以下事情:
  • 創建一個匿名共享內存(android.os.SharedMemory即android提供的匿名共享內存,一般使用android.os.MemoryFile,MemoryFile即是對SharedMemory的一個簡單封裝)
  • 往這個共享內存中寫一個字符數據
  • 將這個匿名共享內存的文件句柄(如FileDescriptor)通過binder機制傳遞給客戶端
客戶端需做以下事情:
  • bindservice獲得服務端的binder對象
  • 調用binder的接口獲得服務端匿名共享內存的文件句柄
  • 通過文件句柄,直接訪問匿名共享內存中的數據,并打印出log。
0條評論
0 / 1000
wbq
18文(wen)章數
0粉絲數
wbq
18 文章 | 0 粉(fen)絲
wbq
18文章數(shu)
0粉絲數
wbq
18 文(wen)章(zhang) | 0 粉絲
原(yuan)創

Binder通信原理

2023-07-24 02:20:54
62
0

1. Binder內存機制

首先我們來看(kan)下安卓應用進程在內(nei)存中(zhong)的分(fen)布,如下圖(tu)所示:

每個(ge)(ge)Android進(jin)(jin)程(cheng),只能運行(xing)在(zai)(zai)自(zi)己的(de)(de)(de)進(jin)(jin)程(cheng)所擁有(you)的(de)(de)(de)虛擬地(di)址空(kong)(kong)(kong)(kong)間(jian)(jian)(jian),如果是(shi)32位的(de)(de)(de)系統(tong),對應(ying)一個(ge)(ge)4GB的(de)(de)(de)虛擬地(di)址空(kong)(kong)(kong)(kong)間(jian)(jian)(jian),其中3GB是(shi)用(yong)(yong)戶(hu)空(kong)(kong)(kong)(kong),1GB是(shi)內(nei)(nei)核(he)空(kong)(kong)(kong)(kong)間(jian)(jian)(jian),而內(nei)(nei)核(he)空(kong)(kong)(kong)(kong)間(jian)(jian)(jian)的(de)(de)(de)大小是(shi)可(ke)(ke)以通(tong)過參(can)數配(pei)置的(de)(de)(de)。對于(yu)用(yong)(yong)戶(hu)空(kong)(kong)(kong)(kong)間(jian)(jian)(jian),不(bu)同進(jin)(jin)程(cheng)之間(jian)(jian)(jian)彼此(ci)是(shi)不(bu)能共(gong)(gong)(gong)享的(de)(de)(de),而內(nei)(nei)核(he)空(kong)(kong)(kong)(kong)間(jian)(jian)(jian)確實可(ke)(ke)以共(gong)(gong)(gong)享的(de)(de)(de)。Client進(jin)(jin)程(cheng)與(yu)Server進(jin)(jin)程(cheng)通(tong)信(xin)(xin),恰(qia)恰(qia)是(shi)利(li)(li)用(yong)(yong)進(jin)(jin)程(cheng)間(jian)(jian)(jian)可(ke)(ke)共(gong)(gong)(gong)享的(de)(de)(de)內(nei)(nei)核(he)內(nei)(nei)空(kong)(kong)(kong)(kong)間(jian)(jian)(jian)來(lai)完成(cheng)(cheng)底層通(tong)信(xin)(xin)工(gong)作的(de)(de)(de),Client端與(yu)Server端進(jin)(jin)程(cheng)往往采用(yong)(yong)ioctl等方法跟內(nei)(nei)核(he)空(kong)(kong)(kong)(kong)間(jian)(jian)(jian)的(de)(de)(de)驅動(dong)進(jin)(jin)行(xing)。(Binder是(shi)Android系統(tong)提供(gong)的(de)(de)(de)一種IPC機制(zhi)。每個(ge)(ge)Android的(de)(de)(de)進(jin)(jin)程(cheng),都可(ke)(ke)以有(you)一塊用(yong)(yong)戶(hu)空(kong)(kong)(kong)(kong)間(jian)(jian)(jian)和(he)內(nei)(nei)核(he)空(kong)(kong)(kong)(kong)間(jian)(jian)(jian)。用(yong)(yong)戶(hu)空(kong)(kong)(kong)(kong)間(jian)(jian)(jian)在(zai)(zai)不(bu)同進(jin)(jin)程(cheng)間(jian)(jian)(jian)不(bu)能共(gong)(gong)(gong)享,內(nei)(nei)核(he)空(kong)(kong)(kong)(kong)間(jian)(jian)(jian)可(ke)(ke)以共(gong)(gong)(gong)享。Binder就是(shi)一個(ge)(ge)利(li)(li)用(yong)(yong)可(ke)(ke)以共(gong)(gong)(gong)享的(de)(de)(de)內(nei)(nei)核(he)空(kong)(kong)(kong)(kong)間(jian)(jian)(jian),完成(cheng)(cheng)高性能的(de)(de)(de)進(jin)(jin)程(cheng)間(jian)(jian)(jian)通(tong)信(xin)(xin)的(de)(de)(de)方案。)

Binder進程間通信效率高的最主要原因是Binder的內存機制:虛擬進程地址空間(用戶空間)和虛擬內核地址空間(內核空間)都映射到同一塊物理內存空間。當Client端與Server端發送數據時,Client(作為數據發送端)先從自己的進程空間把IPC通信數據copy_from_user拷貝到內核空間,而Server端(作為數據接收端)與內核共享數據,不再需要拷貝數據,而是通過內存地址空間的偏移量,即可獲悉內存地址,整個過程只發生一次內存拷貝。
而一般IPC的做法,需要Client端進程空間拷貝到內核空間,再由內核空間拷貝到Server進程空間,會發生兩次拷貝。對于進程和內核虛擬地址映射到同一個物理內存的操作是發生在數據接收端,而數據發送端還是需要將用戶態的數據復制到內核態。
 

2. 和傳統IPC機制相比,谷歌為什么采用Binder

我們先看下Linux中的IPC通信機制:
  • 1、傳統IPC:匿名管道(PIPE)、信號(signal)、有名管道(FIFO)
  • 2、AT&T Unix:共享內存,信號量,消息隊列
  • 3、BSD Unix:Socket
雖然Android繼承Linux內核,但是Linux與Android通信機制是不同的。Android中有大量的C/S(Client/Server)應用方式,這就要求Android內部提供IPC方法,而如果采用Linux所支持的進程通信方式有兩個問題:性能和安全性。那
  • 性能:目前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地址或者文件名都是開放的,只要知道這些接入點的程序都可以對端建立連接,不管怎樣都無法阻止惡意程序通過接收方地址獲得連接。
基于以上原因,Android需要建立一套新的IPC機制來滿足系統對通信方式,傳輸性能和安全性的要求,所以就有了Binder。Binder基于Client/Server通信模式,傳輸過程只需要一次拷貝,為發送發添加UID/PID身份,支持實名Binder也支持匿名Binder,安全性高。下圖為Binder通信過程示例:
 
  • 相比于傳統的跨進程通信手段,通信雙方必須要處理線程同步,內存管理等問題,工作量大,而且問題多,就像我們前面介紹的傳統IPC 命名管道(FIFO) 信號量(semaphore) 消息隊列已經從Android中去掉了,同其他IPC相比,Socket是一種比較成熟的通信手段了,同步控制也很容易實現。Socket用于網絡通信非常合適,但是用于進程間通信就效率很低。
  • Android在架構上一直希望模糊進程的概念,取而代之以組件的概念。應用也不需要關心組件存放的位置、組件運行在那個進程中、組件的生命周期等問題。隨時隨地的,只要擁有Binder對象,就能使用組件的功能。Binder就像一張網,將整個系統的組件,跨進程和線程的組織在一起。
Binder是整個系統的運行的中樞。Android在進程間傳遞數據使用共享內存的方式,這樣數據只需要復制一次就能從一個進程到達另一個進程了(一般IPC都需要兩步,第一步用戶進程復制到內核,第二步再從內核復制到服務進程。)
PS: 整個Android系統架構中,雖然大量采用了Binder機制作為IPC(進程間通信)方式,但是也存在部分其他的IPC方式,比如Zygote通信就是采用socket。
 

3. AIDL

aidl會自動生成一個繼承自Binder的Stub的抽象類(Stub實現自定義接口),重寫了onTransact方法,在onTransact中從data parcel對象中讀取參數,然后根據code調用對應接口方法,并在reply parcel對象中寫入返回結果;
同時也會自動生成一個Proxy的類(Proxy也實現自定義接口),該類持有傳入的IBinder對象,在對應的自定義接口方法中,調用IBinder的transact傳入方法對應的code,參數data parcel,以及返回值reply parcel;
Proxy是Client層用到的,Stub是Server層需要繼承實現的;
/** 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通信的交互示例圖:
Binder通信涉及的主要對象及其作用如下表所示:
概念
作用
Binder代理對象
類型為BpBinder,在用戶空間創建,且執行在Client進程中.會被Client進程中的其他對象引用,另外會引用Binder驅動程序中的Binder引用對象.
Binder引用對象
類型為binder_ref,在Binder驅動程序中創建,被Binder代理對象引用.
Binder實體對象
類型為binder_node,在Binder驅動程序中創建,被Binder引用對象所引用
Binder本地對象
類型為BBinder,在用戶空間中創建,且執行在Server進程中.會被Server進程中其他對象引用,還會被Binder實體對象引用.
 
不管是client還是server,跟binder驅動交互都是通過以下步驟:

一次(ci)Binder通(tong)信最(zui)大(da)可(ke)以傳輸(shu)多大(da)的(de)數據

Binder調用有oneway-異步和非oneway-同步兩種類型。

1MB-8KB的(de)限制來源于哪里呢(ni)?(PS:8k是兩個(ge)pagesize,一個(ge)pagesize是申(shen)請物理內存的(de)最小單元(yuan))

#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();
}
}
}
如果一個進程使用ProcessState這個類來初始化Binder服務,這個進程的Binder內核內存上限就是BINDER_VM_SIZE,也就是1MB-8KB。
virtualvoidonZygoteInit()
{
        sp<ProcessState>proc=ProcessState::self();
ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }
對于普通的APP來說,都是Zygote進程孵化出來的,Zygote進程的初始化Binder服務的時候提前調用了ProcessState這個類,所以普通的APP進程上限就是1MB-8KB。
但是我們可以通過手寫mmap繞過ProcessState的限制;Binder服務的初始化有兩步,open打開Binder驅動,mmap在Binder驅動中申請內核空間內存,所以我們只要手寫open,mmap就可以輕松突破這個限制。但是mmap中有判斷如果傳入申請的空間大于4M則會最多只申請4M;
但是為什么ContentProvider卻能傳輸超過4M或更大的數據呢,其實用的是匿名共享內存;
服務端需做以下事情:
  • 創建一個匿名共享內存(android.os.SharedMemory即android提供的匿名共享內存,一般使用android.os.MemoryFile,MemoryFile即是對SharedMemory的一個簡單封裝)
  • 往這個共享內存中寫一個字符數據
  • 將這個匿名共享內存的文件句柄(如FileDescriptor)通過binder機制傳遞給客戶端
客戶端需做以下事情:
  • bindservice獲得服務端的binder對象
  • 調用binder的接口獲得服務端匿名共享內存的文件句柄
  • 通過文件句柄,直接訪問匿名共享內存中的數據,并打印出log。
文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0