中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

邢臺(tái)建設(shè)網(wǎng)站如何做百度關(guān)鍵詞推廣

邢臺(tái)建設(shè)網(wǎng)站,如何做百度關(guān)鍵詞推廣,哪個(gè)網(wǎng)站建站好,蘇州網(wǎng)站建設(shè)哪里好讀完本文你將了解: IBinderBinderBinder 通信機(jī)制 Binder 驅(qū)動(dòng)Service ManagerBinder 機(jī)制跨進(jìn)程通信流程 Binder 機(jī)制的優(yōu)點(diǎn)總結(jié)Thanks 上篇文章 Android 進(jìn)階7:進(jìn)程通信之 AIDL 中我們雖然跨進(jìn)程通信成功,但是還是有很多疑問的&#xff0…

讀完本文你將了解:

    • IBinder
    • Binder
    • Binder 通信機(jī)制
      • Binder 驅(qū)動(dòng)
      • Service Manager
      • Binder 機(jī)制跨進(jìn)程通信流程
    • Binder 機(jī)制的優(yōu)點(diǎn)
    • 總結(jié)
    • Thanks

上篇文章 Android 進(jìn)階7:進(jìn)程通信之 AIDL 中我們雖然跨進(jìn)程通信成功,但是還是有很多疑問的,比如:

  • AIDL 幫我們做了什么?
  • 為什么要這么寫?
  • 什么是 Binder?

知其然還要知其所以然,一切都要從 Binder 講起。

IBinder

Binder 繼承自 IBinder,所以我們先來了解下它。

public class Binder implements IBinder {...}
public interface IBinder {...}

IBinder 是一個(gè)接口,它代表了一種跨進(jìn)程傳輸?shù)哪芰ΑV灰獙?shí)現(xiàn)了這個(gè)接口,就能將這個(gè)對(duì)象進(jìn)行跨進(jìn)程傳遞。

IBinder 是高性能、輕量級(jí)遠(yuǎn)程調(diào)用機(jī)制的核心部分,它定義了遠(yuǎn)程操作對(duì)象的基本接口。

shixinzhang

這些方法中最關(guān)鍵的一個(gè)是 transact():

public boolean transact(int code, Parcel data, Parcel reply, int flags)throws RemoteException;

與它對(duì)應(yīng)的是 Binder.onTransact()

protected boolean onTransact(int code, Parcel data, Parcel reply,int flags) throws RemoteException {...}

可以看到這兩個(gè)方法非常相似,介紹一下方法中的各個(gè)參數(shù):

  • code:要執(zhí)行的動(dòng)作,類似 Handler 的 msg.what,IBinder 中定義了以下幾個(gè) code
    • PING_TRANSACTION,表示要調(diào)用 pingBinder() 方法
    • DUMP_TRANSACTION,表示要獲取 Binder 內(nèi)部狀態(tài)
    • SHELL_COMMAND_TRANSACTION,執(zhí)行一個(gè) shell 命令
    • INTERFACE_TRANSACTION,詢問被調(diào)用方的接口描述符號(hào)
    • TWEET_TRANSACTION
    • LIKE_TRANSACTION
    • 如果我們需要自定義 code,code 的值范圍需要在 FIRST_CALL_TRANSACTION(0x00000001) 和 LAST_CALL_TRANSACTION(0x00ffffff) 之間
  • data, reply:傳入的參數(shù)和返回的值
  • flags:表示是否需要阻塞等待返回值,有兩個(gè)值
    • 0
    • FLAG_ONEWAY (0x00000001),表示 Client 的 transact() 是單向調(diào)用,執(zhí)行后立即返回

①經(jīng)常的場景是,我們調(diào)用 IBinder.transact() 給一個(gè) IBinder 對(duì)象發(fā)送請(qǐng)求,然后經(jīng)過 Binder Binder.onTransact() 得到調(diào)用,接著遠(yuǎn)程操作的目標(biāo)得到對(duì)應(yīng)的調(diào)用。

這個(gè)過程不僅在同一進(jìn)程中可以進(jìn)行,在跨進(jìn)程(IPC)間也可以完成。

IBinder.transact() 方法是同步的,它被調(diào)用后一直到 Binder.onTransact() 調(diào)用完成后才返回。

②通過 IBinder.transact() 方法傳輸?shù)臄?shù)據(jù)被保存為一個(gè) Parcel 對(duì)象,Parcel 中保存了數(shù)據(jù)以及描述數(shù)據(jù)的元數(shù)據(jù),元數(shù)據(jù)在緩存區(qū)中保持了 IBinder 對(duì)象的引用,這樣不同進(jìn)程都可以訪問同一個(gè)數(shù)據(jù)。

因此在一個(gè) IBinder 對(duì)象寫入 Parcel 對(duì)象然后發(fā)送到另一個(gè)進(jìn)程時(shí),另外那進(jìn)程將這個(gè) IBinder 對(duì)象發(fā)送回去時(shí),原本進(jìn)程接收到的 IBinder 對(duì)象和開始發(fā)送出去的是同一個(gè)引用。

在跨進(jìn)程傳輸后引用沒有改變,這是非常關(guān)鍵的一點(diǎn),這就使得 IBinder/Binder 對(duì)象在跨進(jìn)程通信時(shí)可以作為唯一的標(biāo)識(shí)(比如作為 token 什么的)。

③系統(tǒng)在每個(gè)進(jìn)程中都有一個(gè)處理事物的線程池,這些線程用于調(diào)度其他進(jìn)程對(duì)當(dāng)前進(jìn)程的跨進(jìn)程訪問。

比如說進(jìn)程 A 對(duì)進(jìn)程 B 發(fā)起 IPC 時(shí),A 中調(diào)用 transact() 的線程會(huì)阻塞。B 中的事物線程池收到 A 的 IPC,調(diào)用目標(biāo)對(duì)象的 Binder.onTransact() 方法,然后返回帶結(jié)果的 Parcel。一旦接收到結(jié)果,A 中阻塞的線程得以繼續(xù)執(zhí)行。

這個(gè)過程和線程通信非常相似吧。

④Binder 機(jī)制還支持進(jìn)程間的遞歸調(diào)用。

比如,進(jìn)程 A 向進(jìn)程 B 發(fā)起 IPC,而進(jìn)程 B 在其 Binder.onTransact() 中又用 transact() 向進(jìn)程 A 發(fā)起 IPC,那么進(jìn)程 A 在等待它發(fā)出的調(diào)用返回的同時(shí),也會(huì)響應(yīng) B 的調(diào)用,對(duì)調(diào)用的對(duì)象執(zhí)行 Binder.onTransact() 方法。

這種機(jī)制可以讓我們覺得到跨進(jìn)程的調(diào)用與進(jìn)程內(nèi)的調(diào)用沒什么區(qū)別,這是非常重要的。

⑤在跨進(jìn)程通信時(shí),我們常常想要知道另外進(jìn)程是否可用,IBinder 提供了三個(gè)檢查的方法:

  1. transact()
    • 當(dāng)你調(diào)用的 IBinder 所在進(jìn)程不存在時(shí),會(huì)拋出 RemoteException 異常
  2. pingBinder()
    • 當(dāng)遠(yuǎn)程進(jìn)程不存在時(shí)該方法返回 false
  3. linkToDeath()
    • 這個(gè)方法可以向 IBinder 中注冊(cè)一個(gè) IBinder.DeathRecipient,它將在 IBinder 所在的進(jìn)程退出時(shí)被調(diào)用
/*** 檢查遠(yuǎn)程 Binder 對(duì)象是否存在* * 當(dāng)不存在時(shí)返回 false*/
public boolean pingBinder();
/*** 注冊(cè)一個(gè) Binder 銷毀的監(jiān)聽如果一個(gè) Binder 被銷毀(通常是它所在的進(jìn)程被關(guān)閉),會(huì)回調(diào) DeathRecipient 的 BinderDied 方法* 注意,只會(huì)監(jiān)聽遠(yuǎn)程的 Binder,本地 Binder 一般不會(huì)銷毀,除非當(dāng)前進(jìn)程退出* * 如果要注冊(cè)的 Binder 進(jìn)程已經(jīng)銷毀,就拋出 RemoteException */
public void linkToDeath(DeathRecipient recipient, int flags)throws RemoteException;/*** linkToDeath 注冊(cè)監(jiān)聽回調(diào)的接口*/
public interface DeathRecipient {public void binderDied();
}

Binder

官方文檔中建議:

日常開發(fā)中一般不需要我們?cè)賹?shí)現(xiàn) IBinder,直接使用系統(tǒng)提供的 Binder 即可。

Binder 實(shí)現(xiàn)了 IBinder 定義的操作,它是 Android IPC 的基礎(chǔ),平常接觸到的各種 Manager(ActivityManager, ServiceManager 等),以及綁定 Service 時(shí)都在使用它進(jìn)行跨進(jìn)程操作。

它的存在不會(huì)影響一個(gè)應(yīng)用的生命周期,只要?jiǎng)?chuàng)建它的進(jìn)程在運(yùn)行它就一直可用。

通常我們需要在頂級(jí)的組件(Service, Activity, ContentProvider)中使用它,這樣系統(tǒng)才知道你的進(jìn)程應(yīng)該一直被保留。

下面介紹 Binder 的幾個(gè)關(guān)鍵方法:

實(shí)現(xiàn) IBindertransact() 方法:

public final boolean transact(int code, Parcel data, Parcel reply,int flags) throws RemoteException {if (false) Log.v("Binder", "Transact: " + code + " to " + this);if (data != null) {data.setDataPosition(0);}boolean r = onTransact(code, data, reply, flags);if (reply != null) {reply.setDataPosition(0);}return r;
}

可以看到,這個(gè)方法就是調(diào)用 onTransact() ,然后將返回的結(jié)果再返回回去。

接著看看 onTransact() 方法:

protected boolean onTransact(int code, Parcel data, Parcel reply,int flags) throws RemoteException {if (code == INTERFACE_TRANSACTION) {    //獲取接口描述reply.writeString(getInterfaceDescriptor());return true;} else if (code == DUMP_TRANSACTION) {    //獲取當(dāng)前狀態(tài)ParcelFileDescriptor fd = data.readFileDescriptor();String[] args = data.readStringArray();if (fd != null) {try {dump(fd.getFileDescriptor(), args);} finally {IoUtils.closeQuietly(fd);}}// Write the StrictMode header.if (reply != null) {reply.writeNoException();} else {StrictMode.clearGatheredViolations();}return true;} else if (code == SHELL_COMMAND_TRANSACTION) {    //執(zhí)行 shell 腳本ParcelFileDescriptor in = data.readFileDescriptor();ParcelFileDescriptor out = data.readFileDescriptor();ParcelFileDescriptor err = data.readFileDescriptor();String[] args = data.readStringArray();ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);try {if (out != null) {shellCommand(in != null ? in.getFileDescriptor() : null,out.getFileDescriptor(),err != null ? err.getFileDescriptor() : out.getFileDescriptor(),args, resultReceiver);}} finally {IoUtils.closeQuietly(in);IoUtils.closeQuietly(out);IoUtils.closeQuietly(err);// Write the StrictMode header.if (reply != null) {reply.writeNoException();} else {StrictMode.clearGatheredViolations();}}return true;}return false;
}

也沒看出什么特別的,系統(tǒng)的 Binder.onTransact() 方法只定義了系統(tǒng)要進(jìn)行的操作,我們?nèi)绻麆?chuàng)建自己的 Binder 時(shí),就需要重寫這個(gè)方法,根據(jù) code 對(duì)傳入的參數(shù) data 做相應(yīng)的處理,然后寫入 reply,這樣就能返回操作后的數(shù)據(jù)。

另外一個(gè)關(guān)鍵的方法 attachInterface

public void attachInterface(IInterface owner, String descriptor) {mOwner = owner;mDescriptor = descriptor;
}
/* mObject is used by native code, do not remove or rename */
private long mObject;
private IInterface mOwner;
private String mDescriptor;

這個(gè)方法的作用是將一個(gè)描述符、特定的 IInterface 與當(dāng)前 Binder 綁定起來,這樣后續(xù)調(diào)用 queryLocalInterface 就可以拿到這個(gè) IInterface,那 IInterface 又是什么呢?

public interface IInterface
{/*** Retrieve the Binder object associated with this interface.* You must use this instead of a plain cast, so that proxy objects* can return the correct result.*/public IBinder asBinder();
}

其實(shí)看名字就可以大概猜出來,IInterface 應(yīng)該就是進(jìn)程間通信定義的通用接口,我們通過定義接口,然后再服務(wù)端實(shí)現(xiàn)接口、客戶端調(diào)用接口,就可以實(shí)現(xiàn)跨進(jìn)程通信。

IInterface 里只定義了一個(gè) asBinder() 方法,這個(gè)方法可以返回當(dāng)前接口關(guān)聯(lián)的 Binder 對(duì)象。

Binder 通信機(jī)制

上面介紹了 Binder 類以及相關(guān)的方法,但是這只是 Binder 機(jī)制的最基礎(chǔ)部分。

我們平??吹奈恼禄蛘呙嬖嚂r(shí),說的 Binder 其實(shí)是范圍更大的整個(gè) “Binder 消息通信機(jī)制”。

借用老羅的 Android進(jìn)程間通信(IPC)機(jī)制Binder簡要介紹和學(xué)習(xí)計(jì)劃 中對(duì) Binder 通信機(jī)制的介紹:

shixinzhang

在 Android 系統(tǒng)的 Binder 機(jī)制中,由四個(gè)組件組成,分別是:

  • Client
  • Server
  • ServiceManager:提供輔助管理 Server 的功能
  • Binder 驅(qū)動(dòng)程序:整個(gè)機(jī)制的核心

Binder 驅(qū)動(dòng)

驅(qū)動(dòng)程序一般指的是設(shè)備驅(qū)動(dòng)程序(Device Driver),是一種可以使計(jì)算機(jī)和設(shè)備通信的特殊程序。相當(dāng)于硬件的接口,操作系統(tǒng)只有通過這個(gè)接口,才能控制硬件設(shè)備的工作。

我們知道,在 Linux 系統(tǒng)中,內(nèi)存空間分為兩部分:

  • 用戶空間:運(yùn)行著應(yīng)用程序
  • 內(nèi)核空間:運(yùn)行著系統(tǒng)內(nèi)核和驅(qū)動(dòng)

shixinzhang

用戶空間中的進(jìn)程無法直接訪問內(nèi)核空間,需要通過上圖中的 System Call Interface (系統(tǒng)調(diào)用接口),通過這個(gè)統(tǒng)一入口,所有資源訪問都是在內(nèi)核的控制下執(zhí)行,這樣可以避免用戶程序?qū)ο到y(tǒng)資源的越權(quán)訪問,從而保障了系統(tǒng)的安全和穩(wěn)定。

同樣的,用戶空間中的進(jìn)程直接也不可以直接訪問數(shù)據(jù),需要通過內(nèi)核空間進(jìn)行中轉(zhuǎn)。

在 Binder 機(jī)制中,由 Binder 驅(qū)動(dòng)負(fù)責(zé)完成這個(gè)中轉(zhuǎn)操作,主要過程如下:

  • 當(dāng) Client 向 Server 發(fā)起 IPC 請(qǐng)求時(shí),Client 會(huì)先將請(qǐng)求數(shù)據(jù)從用戶空間拷貝到內(nèi)核空間
  • 數(shù)據(jù)被拷貝到內(nèi)核空間之后,驅(qū)動(dòng)程序?qū)?nèi)核空間中的數(shù)據(jù)拷貝到 Server 位于用戶空間的緩存中

這樣,就成功的將 Client 進(jìn)程中的請(qǐng)求數(shù)據(jù)傳遞到了 Server 進(jìn)程中。

實(shí)際上,Binder 驅(qū)動(dòng)是整個(gè) Binder 機(jī)制的核心。除了實(shí)現(xiàn)數(shù)據(jù)傳輸之外,Binder 驅(qū)動(dòng)還是實(shí)現(xiàn)線程控制(通過中斷等待隊(duì)列實(shí)現(xiàn)線程的等待/喚醒),以及 UID/PID 等安全機(jī)制的保證。
http://wangkuiwu.github.io/2014/09/01/Binder-Introduce/

Service Manager

ServiceManager 運(yùn)行在用戶空間,它負(fù)責(zé)管理 Service 注冊(cè)與查詢。

看下 ServiceManager 的代碼:

public final class ServiceManager {private static final String TAG = "ServiceManager";private static IServiceManager sServiceManager;private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();private static IServiceManager getIServiceManager() {if (sServiceManager != null) {return sServiceManager;}// Find the service managersServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());return sServiceManager;}/*** 根據(jù) Service 名稱獲取 Service*/public static IBinder getService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {//如果不存在就去 IServiceManager 中找,這時(shí)可能會(huì)阻塞return getIServiceManager().getService(name);}} catch (RemoteException e) {Log.e(TAG, "error in getService", e);}return null;}/*** 添加一個(gè) Service 到 Manager 中*/public static void addService(String name, IBinder service) {try {getIServiceManager().addService(name, service, false);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);}}/*** 添加一個(gè) Service 到 Manager 中,如果 allowIsolated 為 true 表示運(yùn)行在沙盒中的進(jìn)程也可以訪問這個(gè) Service*/public static void addService(String name, IBinder service, boolean allowIsolated) {try {getIServiceManager().addService(name, service, allowIsolated);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);}}/*** Retrieve an existing service called @a name from the* service manager.  Non-blocking.*/public static IBinder checkService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {return getIServiceManager().checkService(name);}} catch (RemoteException e) {Log.e(TAG, "error in checkService", e);return null;}}/*** 獲取 Service 列表*/public static String[] listServices() {try {return getIServiceManager().listServices();} catch (RemoteException e) {Log.e(TAG, "error in listServices", e);return null;}}/*** 當(dāng)前進(jìn)程首次被 activity manager 創(chuàng)建時(shí)調(diào)用這個(gè)方法 */public static void initServiceCache(Map<String, IBinder> cache) {if (sCache.size() != 0) {throw new IllegalStateException("setServiceCache may only be called once");}sCache.putAll(cache);}
}

可以看到 ServiceManager 提供了 Service 的添加和查詢,其中主要操作都是通過 IServiceManager,它是何方神圣?

public interface IServiceManager extends IInterface
{/*** 獲取一個(gè) Service,不存在就會(huì)阻塞幾秒*/public IBinder getService(String name) throws RemoteException;/*** 不阻塞的獲取 Service*/public IBinder checkService(String name) throws RemoteException;public void addService(String name, IBinder service, boolean allowIsolated)throws RemoteException;public String[] listServices() throws RemoteException;/*** 為 Service Manager 添加權(quán)限,具體作用暫不追究*/public void setPermissionController(IPermissionController controller)throws RemoteException;static final String descriptor = "android.os.IServiceManager";//定義了一些用于調(diào)用 transact() 方法的 codeint GET_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;int CHECK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;int ADD_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+2;int LIST_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+3;int CHECK_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+4;int SET_PERMISSION_CONTROLLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+5;
}

可以看到 IServiceManager 是一個(gè)接口,它定義了管理 Service 的一些方法,同時(shí)繼承了 IInterface。最常見的實(shí)現(xiàn)是 BnServiceManager.getDefault()。

Binder 機(jī)制跨進(jìn)程通信流程

上面兩節(jié)簡單介紹了 Binder 機(jī)制中非常重要的兩部分,ServiceManager 和 Binder 驅(qū)動(dòng)。

在 Binder 機(jī)制的四個(gè)部分中, Client、Server 和 ServiceManager 運(yùn)行在用戶空間,Binder 驅(qū)動(dòng)程序運(yùn)行內(nèi)核空間。

Binder 就是一種把這四個(gè)組件粘合在一起的粘結(jié)劑。

這個(gè)流程是如何進(jìn)行的呢?

借用 Android Binder機(jī)制(一) Binder的設(shè)計(jì)和框架 的圖片:

shixinzhang

上圖簡單介紹(節(jié)選自 http://wangkuiwu.github.io/2014/09/01/Binder-Introduce/):

  • Binder實(shí)體
    • Binder 實(shí)體實(shí)際上是內(nèi)核中 binder_node 結(jié)構(gòu)體的對(duì)象,它的作用是在內(nèi)核中保存 Server 和ServiceManager 的信息(例如,Binder 實(shí)體中保存了 Server 對(duì)象在用戶空間的地址)
    • Binder 實(shí)體是 Server 在 Binder 驅(qū)動(dòng)中的存在形式,內(nèi)核通過 Binder 實(shí)體可以找到用戶空間的Server對(duì)象
    • 在上圖中,Server 和 ServiceManager 在 Binder 驅(qū)動(dòng)中都對(duì)應(yīng)的存在一個(gè) Binder 實(shí)體
  • Binder 引用
    • Binder引用實(shí)際上是內(nèi)核中 binder_ref 結(jié)構(gòu)體的對(duì)象,是某一個(gè) Binder 實(shí)體的引用,通過Binder 引用可以在內(nèi)核中找到對(duì)應(yīng)的 Binder 實(shí)體
    • 如果將 Server 看作是 Binder 實(shí)體的話,那么 Client 就好比 Binder 引用,Client 通過保存一個(gè)Server 對(duì)象的 Binder 引用,再通過該 Binder 引用在內(nèi)核中找到對(duì)應(yīng)的 Binder 實(shí)體,進(jìn)而找到Server 對(duì)象,然后將通信內(nèi)容發(fā)送給 Server 對(duì)象
  • 遠(yuǎn)程服務(wù)
    • 本地服務(wù)的代理,通過調(diào)用遠(yuǎn)程服務(wù)可以間接調(diào)用本地服務(wù)

1.Client、Server 和 ServiceManager 處于用戶空間的不同進(jìn)程。
2.Binder 實(shí)體和 Binder 引用都是內(nèi)核(即 Binder 驅(qū)動(dòng))中的數(shù)據(jù)結(jié)構(gòu)。

它們的關(guān)系如下:

shixinzhang

每一個(gè) Server 在內(nèi)核中就表現(xiàn)為一個(gè) Binder 實(shí)體,而每一個(gè) Client 則表現(xiàn)為一個(gè) Binder 引用。這樣,每個(gè) Binder 引用都對(duì)應(yīng)一個(gè) Binder 實(shí)體,而每個(gè) Binder 實(shí)體則可以多個(gè) Binder 引用。

Binder 跨進(jìn)程通訊流程主要為如下 4 步:

  1. ServiceManager 初始化
    • 當(dāng)該應(yīng)用程序啟動(dòng)時(shí),ServiceManager 會(huì)和 Binder 驅(qū)動(dòng)進(jìn)行通信,告訴 Binder 驅(qū)動(dòng)它是服務(wù)管理者
    • Binder 驅(qū)動(dòng)新建 ServiceManager 對(duì)應(yīng)的 Binder 實(shí)體
  2. Server 向 ServiceManager 注冊(cè)自己
    • Server 向 Binder 驅(qū)動(dòng)發(fā)起注冊(cè)請(qǐng)求,Binder 為它創(chuàng)建 Binder 實(shí)體
    • 然后如果 ServiceManager 中沒有這個(gè) Server 時(shí)就添加 Server 名稱與 Binder 引用到它的 Binder 引用表
  3. Client 獲取遠(yuǎn)程服務(wù)
    • Client 首先會(huì)向 Binder 驅(qū)動(dòng)發(fā)起獲取服務(wù)的請(qǐng)求,傳遞要獲取的服務(wù)名稱
    • Binder 驅(qū)動(dòng)將該請(qǐng)求轉(zhuǎn)發(fā)給 ServiceManager 進(jìn)程
    • ServiceManager 查找到 Client 需要的 Server 對(duì)應(yīng)的 Binder 實(shí)體的 Binder 引用信息,然后通過 Binder 驅(qū)動(dòng)反饋給 Client
    • Client 收到 Server 對(duì)應(yīng)的 Binder 引用后,會(huì)創(chuàng)建一個(gè) Server 對(duì)應(yīng)的遠(yuǎn)程服務(wù)(即 Server 在當(dāng)前進(jìn)程的代理)
  4. Client 通過代理調(diào)用 Server
    • Client 調(diào)用遠(yuǎn)程服務(wù),遠(yuǎn)程服務(wù)收到 Client 請(qǐng)求之后,會(huì)和 Binder 驅(qū)動(dòng)通信
    • 因?yàn)檫h(yuǎn)程服務(wù)中有 Server 的 Binder 引用信息,因此驅(qū)動(dòng)就能輕易的找到對(duì)應(yīng)的 Server,進(jìn)而將Client 的請(qǐng)求內(nèi)容發(fā)送 Server

Binder 機(jī)制的優(yōu)點(diǎn)

對(duì)比 Linux 上的其他進(jìn)程通信方式(管道/消息隊(duì)列/共享內(nèi)存/信號(hào)量/Socket),Binder 機(jī)制的優(yōu)點(diǎn)有以下幾點(diǎn):

  1. 高效簡單

    • 通過驅(qū)動(dòng)在內(nèi)核空間拷貝數(shù)據(jù),不需要額外的同步處理
    • 對(duì)比 Socket 等傳輸效率高
  2. 安全

    • Binder 機(jī)制為每個(gè)進(jìn)程分配了 UID/PID 來作為鑒別身份的標(biāo)示,并且在 Binder 通信時(shí)會(huì)根據(jù)UID/PID 進(jìn)行有效性檢測
  3. Client/Server 架構(gòu)

    • 這種架構(gòu)使得通訊更為簡單

總結(jié)

Binder 機(jī)制的學(xué)習(xí)過程是痛苦的 T.T,即使光看 Java 層也費(fèi)了不少功夫,這可能是由于我實(shí)戰(zhàn)中沒有遇到,光看源碼和抽象概念掌握太慢的原因吧。

本文簡單介紹了 Binder 機(jī)制,參考了很多優(yōu)秀的文章,真佩服他們!

借用《Android 開發(fā)藝術(shù)探索》對(duì) Binder 的概括:

  • 從代碼角度來看,Binder 是一個(gè)類,實(shí)現(xiàn)了 IBinder 接口;
  • 從來源看,Binder 來自于 OpenBinder,是 Android IPC 機(jī)制中的一種,Binder 還可以理解成一個(gè)虛擬物理設(shè)備,設(shè)備驅(qū)動(dòng)是dev/binder;
  • 從 Framework 層看,Binder 是 Service Manager 連接各種Manager(ActivityManager,PackageManager…) 和相應(yīng)Service (ActivityManagerService, PackageManagerService…) 的橋梁;
  • 從客戶端看,Binder 是客戶端服務(wù)器通訊的媒介

在對(duì) Binder 有了一定理解后,下篇文章我們就去看看 AIDL 幫我們做了什么。

Thanks

《Android 開發(fā)藝術(shù)探索》
https://developer.android.com/reference/android/os/IBinder.html
http://blog.csdn.net/luoshengyang/article/details/6618363
http://blog.csdn.net/luoshengyang/article/details/6642463
http://weishu.me/2016/01/12/binder-index-for-newer/
http://wangkuiwu.github.io/2014/09/01/Binder-Introduce/
http://blog.csdn.net/u010132993/article/details/72582655

http://m.risenshineclean.com/news/59432.html

相關(guān)文章:

  • 微網(wǎng)站促銷版cps推廣
  • 石家莊做商城網(wǎng)站的公司網(wǎng)站點(diǎn)擊量與排名
  • 自己做網(wǎng)站流程有道搜索引擎入口
  • 吉林市網(wǎng)站推廣百度宣傳推廣費(fèi)用
  • 織夢(mèng)網(wǎng)站 聯(lián)系方式修改今天的病毒感染情況
  • 湖北住房和城鄉(xiāng)建設(shè)部網(wǎng)站直接下載app
  • 網(wǎng)站備案在外地怎樣創(chuàng)建網(wǎng)站平臺(tái)
  • 兩學(xué)一做注冊(cè)網(wǎng)站嗎網(wǎng)絡(luò)廣告有哪些形式
  • 平面設(shè)計(jì)比較好的網(wǎng)站廣告投放平臺(tái)系統(tǒng)
  • 金色世紀(jì)做網(wǎng)站的是哪個(gè)崗位發(fā)布推廣信息的網(wǎng)站
  • 在縣城怎么做網(wǎng)站公司seo教程優(yōu)化
  • 做網(wǎng)站不打廣告怎么賺錢網(wǎng)絡(luò)營銷是什么工作
  • 公司微網(wǎng)站怎么建設(shè)廣州線上教學(xué)
  • 動(dòng)易網(wǎng)站后臺(tái)密碼破解寧夏百度推廣代理商
  • 航達(dá)建設(shè)網(wǎng)站上海優(yōu)質(zhì)網(wǎng)站seo有哪些
  • 有沒有什么做統(tǒng)計(jì)的網(wǎng)站網(wǎng)絡(luò)營銷比較好的企業(yè)
  • 如何解決網(wǎng)站只收錄首頁的一些辦法小程序制作
  • cms網(wǎng)站地圖模板東莞搜索引擎推廣
  • 開淘寶店和做網(wǎng)站有什么區(qū)別福鼎網(wǎng)站優(yōu)化公司
  • 直接打域名訪問網(wǎng)站關(guān)鍵詞推廣工具
  • 網(wǎng)站制作設(shè)及的技術(shù)產(chǎn)品營銷策劃方案3000字
  • 廣州定制網(wǎng)站建設(shè)廣東seo網(wǎng)站推廣代運(yùn)營
  • 成都網(wǎng)站開發(fā)哪個(gè)好深圳seo優(yōu)化排名
  • 嵌入式培訓(xùn)班多少錢seo優(yōu)化推廣軟件
  • 企業(yè)網(wǎng)站備案 名稱沈陽seo博客
  • 伊通縣建設(shè)局網(wǎng)站常德政府網(wǎng)站
  • 學(xué)校英語網(wǎng)站欄目名稱域名備案
  • WordPress漢化卡片式主題長嶺網(wǎng)站優(yōu)化公司
  • 做直播網(wǎng)站需要什么環(huán)球軍事網(wǎng)
  • 網(wǎng)站建設(shè)好之后怎么自己推廣免費(fèi)推廣引流平臺(tái)有哪些