麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Binder工作機(jī)制詳解(應(yīng)用層)

2019-11-09 14:16:28
字體:
供稿:網(wǎng)友

轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/wu371894545/article/details/54962860

一、Binder機(jī)制概述

在Android開發(fā)中,很多時(shí)候我們需要用到進(jìn)程間通信,所謂進(jìn)程間通信,實(shí)現(xiàn)進(jìn)程間通信的機(jī)制有很多種,比如說socket、pipe等,Android中進(jìn)程間通信的方式主要有三種:

1.標(biāo)準(zhǔn)linux Kernel IPC 接口;

2.標(biāo)準(zhǔn)D-BUS接口;

3.Binder接口。

其中,Binder機(jī)制是使用最且最被認(rèn)可的,因?yàn)锽inder機(jī)制有以下優(yōu)點(diǎn):

1.相對(duì)于其它IPC機(jī)制,Binder機(jī)制更加簡(jiǎn)潔和快速;

2.消耗的內(nèi)存相對(duì)更少;

3.傳統(tǒng)的IPC機(jī)制可能會(huì)增加進(jìn)程的開銷,以及出現(xiàn)進(jìn)程過載和安全漏洞,Binder機(jī)制則有效避免和解決了這些問題。

Binder機(jī)制是Android系統(tǒng)的核心機(jī)制,幾乎貫穿于整個(gè)Android系統(tǒng),Android系統(tǒng)基本上可以看作是一個(gè)基于binder通信機(jī)制的C/S架構(gòu),Binder就像網(wǎng)絡(luò),把Android系統(tǒng)的各個(gè)部分連接到了一起。利用Binder機(jī)制,可以實(shí)現(xiàn)以下功能:

1.用驅(qū)動(dòng)程序來推進(jìn)進(jìn)程間通信;

2.通過共享內(nèi)存來提高性能;

3.為進(jìn)程請(qǐng)求分配每個(gè)進(jìn)程的線程池;

4.針對(duì)系統(tǒng)中的對(duì)象引入了引用計(jì)數(shù)和跨進(jìn)程的對(duì)象引用映射;

5.進(jìn)程間同步調(diào)用。

二.什么是Binder

1. 直觀來說,Binder是Android中的一個(gè)類,它繼承了IBinder接口

2. 從IPC角度來說,Binder是Android中的一種跨進(jìn)程通信方式,Binder還可以理解為一種虛擬的物理設(shè)備,它的設(shè)備驅(qū)動(dòng)是/dev/binder,該通信方式在Linux中沒有

3. 從Android Framework角度來說,Binder是ServiceManager連接各種Manager(ActivityManager、WindowManager,etc)和相應(yīng)ManagerService的橋梁

4. 從Android應(yīng)用層來說,Binder是客戶端和服務(wù)端進(jìn)行通信的媒介,當(dāng)你bindService的時(shí)候,服務(wù)端會(huì)返回一個(gè)包含了服務(wù)端業(yè)務(wù)調(diào)用的Binder對(duì)象,通過這個(gè)Binder對(duì)象,客戶端就可以獲取服務(wù)端提供的服務(wù)或者數(shù)據(jù),這里的服務(wù)包括普通服務(wù)和基于AIDL的服務(wù)

三、為什么Android內(nèi)核要使用Binder

Android中有大量的CS(Client-Server)應(yīng)用方式,這就要求Android內(nèi)部提供IPC方法,而linux所支持的進(jìn)程通信方式有兩個(gè)問題:性能和安全性。

目前l(fā)inux支持的IPC包括傳統(tǒng)的管道,System V IPC(消息隊(duì)列/共享內(nèi)存/信號(hào)量),以及socket,但只有socket支持Client-Server的通信方式,由于socket是一套通用的網(wǎng)絡(luò)通信方式,其傳輸效率低下切有很大的開銷,比如socket的連接建立過程和中斷連接過程都是有一定開銷的。消息隊(duì)列和管道采用存儲(chǔ)-轉(zhuǎn)發(fā)方式,即數(shù)據(jù)先從發(fā)送方緩存區(qū)拷貝到內(nèi)核開辟的緩存區(qū)中,然后再從內(nèi)核緩存區(qū)拷貝到接收方緩存區(qū),至少有兩次拷貝過程。共享內(nèi)存雖然無需拷貝,但控制復(fù)雜,難以使用。

在安全性方面,Android作為一個(gè)開放式,擁有眾多開發(fā)者的的平臺(tái),應(yīng)用程序的來源廣泛,確保智能終端的安全是非常重要的。終端用戶不希望從網(wǎng)上下載的程序在不知情的情況下偷窺隱私數(shù)據(jù),連接無線網(wǎng)絡(luò),長(zhǎng)期操作底層設(shè)備導(dǎo)致電池很快耗盡等等。傳統(tǒng)IPC沒有任何安全措施,完全依賴上層協(xié)議來確保。首先傳統(tǒng)IPC的接收方無法獲得對(duì)方進(jìn)程可靠的UID/PID(用戶ID/進(jìn)程ID),從而無法鑒別對(duì)方身份。Android為每個(gè)安裝好的應(yīng)用程序分配了自己的UID,故進(jìn)程的UID是鑒別進(jìn)程身份的重要標(biāo)志。使用傳統(tǒng)IPC只能由用戶在數(shù)據(jù)包里填入U(xiǎn)ID/PID,但這樣不可靠,容易被惡意程序利用。可靠的身份標(biāo)記只有由IPC機(jī)制本身在內(nèi)核中添加。其次傳統(tǒng)IPC訪問接入點(diǎn)是開放的,無法建立私有通道。比如命名管道的名稱,system V的鍵值,socket的ip地址或文件名都是開放的,只要知道這些接入點(diǎn)的程序都可以和對(duì)端建立連接,不管怎樣都無法阻止惡意程序通過猜測(cè)接收方地址獲得連接。

基于以上原因,Android需要建立一套新的IPC機(jī)制來滿足系統(tǒng)對(duì)通信方式,傳輸性能和安全性的要求,這就是Binder。Binder基于 Client-Server通信模式,傳輸過程只需一次拷貝,為發(fā)送發(fā)添加UID/PID身份,既支持實(shí)名Binder也支持匿名Binder,安全性高。

二、從自動(dòng)生成的AIDL文件中分析Binderpackage com.ryg.chapter_2.aidl;public interface IBookManager extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.ryg.chapter_2.aidl.IBookManager { PRivate static final java.lang.String DESCRIPTOR = "com.ryg.chapter_2.aidl.IBookManager"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.ryg.chapter_2.aidl.IBookManager * interface, generating a proxy if needed. */ public static com.ryg.chapter_2.aidl.IBookManager asInterface( android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.ryg.chapter_2.aidl.IBookManager))) { return ((com.ryg.chapter_2.aidl.IBookManager) iin); } return new com.ryg.chapter_2.aidl.IBookManager.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_getBookList: { data.enforceInterface(DESCRIPTOR); java.util.List<com.ryg.chapter_2.aidl.Book> _result = this .getBookList(); reply.writeNoException(); reply.writeTypedList(_result); return true; } case TRANSACTION_addBook: { data.enforceInterface(DESCRIPTOR); com.ryg.chapter_2.aidl.Book _arg0; if ((0 != data.readInt())) { _arg0 = com.ryg.chapter_2.aidl.Book.CREATOR .createFromParcel(data); } else { _arg0 = null; } this.addBook(_arg0); reply.writeNoException(); return true; } case TRANSACTION_registerListener: { data.enforceInterface(DESCRIPTOR); com.ryg.chapter_2.aidl.IOnNewBookArrivedListener _arg0; _arg0 = com.ryg.chapter_2.aidl.IOnNewBookArrivedListener.Stub .asInterface(data.readStrongBinder()); this.registerListener(_arg0); reply.writeNoException(); return true; } case TRANSACTION_unregisterListener: { data.enforceInterface(DESCRIPTOR); com.ryg.chapter_2.aidl.IOnNewBookArrivedListener _arg0; _arg0 = com.ryg.chapter_2.aidl.IOnNewBookArrivedListener.Stub .asInterface(data.readStrongBinder()); this.unregisterListener(_arg0); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.ryg.chapter_2.aidl.IBookManager { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public java.util.List<com.ryg.chapter_2.aidl.Book> getBookList() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.util.List<com.ryg.chapter_2.aidl.Book> _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0); _reply.readException(); _result = _reply .createTypedArrayList(com.ryg.chapter_2.aidl.Book.CREATOR); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public void addBook(com.ryg.chapter_2.aidl.Book book) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); if ((book != null)) { _data.writeInt(1); book.writeToParcel(_data, 0); } else { _data.writeInt(0); } mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public void registerListener( com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeStrongBinder((((listener != null)) ? (listener .asBinder()) : (null))); mRemote.transact(Stub.TRANSACTION_registerListener, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public void unregisterListener( com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeStrongBinder((((listener != null)) ? (listener .asBinder()) : (null))); mRemote.transact(Stub.TRANSACTION_unregisterListener, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); static final int TRANSACTION_registerListener = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2); static final int TRANSACTION_unregisterListener = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3); } public java.util.List<com.ryg.chapter_2.aidl.Book> getBookList() throws android.os.RemoteException; public void addBook(com.ryg.chapter_2.aidl.Book book) throws android.os.RemoteException; public void registerListener( com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException; public void unregisterListener( com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException;}(1):首先,它申明了倆個(gè)方法getBookList和addBook,顯然這就是我們?cè)贗bookManager.aidl中所申明的方法。同時(shí)它還倆個(gè)整形的id分別用于表示這倆個(gè)方法。(2):接著,它申明了一個(gè)內(nèi)部類Stub,這個(gè)Stub就是一個(gè)Binder類,當(dāng)客戶端和服務(wù)端都位于同一個(gè)進(jìn)程時(shí),方法調(diào)用不會(huì)走跨進(jìn)程的transact過程,而當(dāng)倆者位于不同進(jìn)程時(shí),方法調(diào)用走transact過程,這個(gè)邏輯是由于Stub的內(nèi)部代理類Proxy來完成。這么看來,IbookManager這個(gè)接口的確很簡(jiǎn)單,但是我們也應(yīng)該認(rèn)識(shí)到,這個(gè)接口的核心實(shí)現(xiàn)就是它的內(nèi)部類Stub和Stub的內(nèi)部代理類Proxy.DESCRIPTORBinder的唯一標(biāo)識(shí),一般用當(dāng)前Binder的類名表示,比如本例中的com.ryg.chapter_2.aidl.IBookManagerasInterface用于將服務(wù)端的Binder對(duì)象轉(zhuǎn)換成客戶端所需的AIDL接口對(duì)象的類型,這種轉(zhuǎn)換過程是區(qū)分進(jìn)程的,如果客戶端和服務(wù)端位于同一進(jìn)程,那么此方法返回的就是服務(wù)端的Stub對(duì)象本身,否則返回的就是系統(tǒng)封裝后的Stub.proxy對(duì)象。asBinder此方法返回當(dāng)前Binder對(duì)象onTransact這個(gè)方法運(yùn)行在服務(wù)端中的Binder線程池中,當(dāng)客戶端發(fā)起跨進(jìn)程請(qǐng)求時(shí),遠(yuǎn)程請(qǐng)求會(huì)通過底層封裝后交由此方法來處理。服務(wù)端通過code可以確定客戶端所請(qǐng)求的目標(biāo)到底是什么。當(dāng)目標(biāo)方法執(zhí)行完畢后,就向reply中寫入返回值。需要注意的是,如果此方法返回false,那么客戶端的請(qǐng)求會(huì)失敗,因此我們可以利用這個(gè)特性來進(jìn)行權(quán)限認(rèn)證,畢竟我們也不希望隨便一個(gè)進(jìn)程都能遠(yuǎn)程調(diào)用我們的服務(wù)。雖然我們知道了BInder的工作機(jī)制,但是還需要說明倆點(diǎn):1.當(dāng)客戶端發(fā)起遠(yuǎn)程請(qǐng)求時(shí),由于當(dāng)前線程會(huì)被掛起直至服務(wù)端進(jìn)程返回?cái)?shù)據(jù),所以如果一個(gè)遠(yuǎn)程方法很耗時(shí),那么不能在UI線程中發(fā)起此遠(yuǎn)程請(qǐng)求。2.由于服務(wù)器的Binder方法運(yùn)行在Binder線程池,所以Binder方法不管是否耗時(shí)都應(yīng)該采用同步的方式去實(shí)現(xiàn)。,因?yàn)樗呀?jīng)運(yùn)行在一個(gè)線程中了。

四、Binder機(jī)制的工作流程

從上面我們可以知道Binder工作機(jī)制的流程:

1.客戶端獲取服務(wù)端的帶來對(duì)象(proxy)。我們需要明確的是客戶端進(jìn)程并不能直接操作服務(wù)端中的方法,如果要操作服務(wù)端中的方法,那么有一個(gè)可行的解決方法就是在客戶端建立一個(gè)服務(wù)端進(jìn)程的代理對(duì)象,這個(gè)代理對(duì)象具備和服務(wù)端進(jìn)程一樣的功能,要訪問服務(wù)端進(jìn)程中的某個(gè)方法,只需要訪問代理對(duì)象中對(duì)應(yīng)的方法即可;

2.客戶端通過調(diào)用代理對(duì)象向服務(wù)端發(fā)送請(qǐng)求。

3.代理對(duì)象將用戶請(qǐng)求通過Binder驅(qū)動(dòng)發(fā)送到服務(wù)器進(jìn)程;

4.服務(wù)端進(jìn)程處理客戶端發(fā)過來的請(qǐng)求,處理完之后通過Binder驅(qū)動(dòng)返回處理結(jié)果給客戶端的服務(wù)端代理對(duì)象;

5.代理對(duì)象將請(qǐng)求結(jié)果進(jìn)一步返回給客戶端進(jìn)程。

通過以上5個(gè)步驟,就完成了一次Binder通信。

下面我們給出一張Binder的工作機(jī)制圖

 源碼下載
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 日韩激情| 国产精品久久久久久久久久东京 | 亚洲视频在线网 | 今井夏帆av一区二区 | 国产精品午夜未成人免费观看 | 日本看片一区二区三区高清 | 欧美18videos性处按摩 | 精品在线观看一区 | av在线一区二区三区 | 在线观看一二三 | 欧洲色阁中文字幕 | 毛片免费看电影 | 少妇一级淫片高潮流水电影 | 成人免费毛片片v | 亚洲一区二区三区四区精品 | 国产亚洲精品成人a | 国产一级一片免费播放 | 免费a级毛片大学生免费观看 | 欧美日韩在线免费观看 | 黄色成年在线观看 | 国产女厕一区二区三区在线视 | 色综合久久久久综合99 | 2019天天干夜夜操 | 亚洲白嫩在线观看 | 欧美人与牲禽动交精品一区 | 动漫孕妇被羞羞视频 | 最新在线中文字幕 | 欧美h版电影在线观看 | 成人啪啪色婷婷久 | 国产视频在线播放 | 在线亚州 | 欧美一区二区三区不卡免费观看 | 国产精品av久久久久久久久久 | 有兽焉免费动画 | 国产精品一区二区视频 | 九九视频精品在线观看 | 久久久一区二区三区四区 | 欧美日本一 | xnxx 日本免费 | 国产精品久久久网站 | 污视频在线免费播放 |