日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

              歡迎訪問 生活随笔!

              生活随笔

              當前位置: 首頁 > 运维知识 > Android >内容正文

              Android

              Android Binder机制(1501210451 张志康)

              發布時間:2025/3/15 Android 46 豆豆
              生活随笔 收集整理的這篇文章主要介紹了 Android Binder机制(1501210451 张志康) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

              本文主要分析native層和Java層的Android binder通信機制。

              binder是Android最為常見的進程通信機制之一,其驅動和通信庫是binder的核心,分別由C和C++編寫,應用程序通過JNI同底層庫進行關聯,也就是native層驅動和通信庫通過Java層包裝后被Java層調用。

              源代碼網址:http://androidxref.com/4.2_r1/

              參考博客:http://blog.csdn.net/coding_glacier/article/details/7520199

              一、native層整體通信流程

              • 通信流程概要

                在探究binder通信流程之前,首先我們需要了解Binder機制的四個組件:Client、Server、Service Manager和Binder驅動程序。關系如圖:

                應用程序最終目的是完成Client組件和Server組件之間的通信。ServiceManger對于大家而言是一個公共接入點,0便是ServiceManger的句柄值。

                從表面看通信建立的流程便是注冊和獲取的過程: 1、client通過參數(Parcel包)傳遞進行通信請求;

                2、在收到通信請求時,Server組件需要通過0這個句柄值訪問ServiceManger,在ServiceManger中注冊一個binder實體。并關聯一個字符串;

                3、Client組件通過0這個標識去訪問ServiceManger,通過一個字符去查詢Server組件的引用,此ServiceManger將Server注冊的binder實體的一個引用傳遞給Client端,此時client便可根據這個引用同server進行通信了。

                由以上可知,在收到請求時server將一個binder實體傳遞給C進程,而client得到的只是binder的一個引用,進而調用binder實體的函數。BpBinder和BBinder分別代表binder 的引用和實體,它們均繼承自IBinder類。

                在描述具體流程之前我們先來了解binder通信中需要用到的三個主要基類:

                1.基類IInterface: 為server端提供接口,它的子類聲明了service能夠實現的所有的方法;

                2.基類IBinder BBinder與BpBinder均為IBinder的子類,因此可以看出IBinder定義了binder IPC的通信協議,BBinder與BpBinder在這個協議框架內進行的收和發操作,構建了基本的binder IPC機制。

                3.基類BpRefBase client端在查詢SM獲得所需的的BpBinder后,BpRefBase負責管理當前獲得的BpBinder實例。

              • ServiceManger

                首先我們來了解一下在通信流程中ServiceManger所做的工作。

                ServiceManger是一個linux級進程,是一個service管理器(service向SM注冊是,service就是一個client,而ServiceManger便是server),即我們前邊提到的:每一個service被使用之前,均要向ServiceManger注冊,客戶端通過查詢ServiceManger是否存在此服務來獲取service的handle(標識符)。

                ServiceManger入口函數為:service_manager.c位于:/frameworks/base/cmds/servicemanager/int main(int argc, char **argv){struct binder_state *bs;void *svcmgr = BINDER_SERVICE_MANAGER;bs = binder_open(128*1024);if (binder_become_context_manager(bs)) {ALOGE("cannot become context manager (%s)\n", strerror(errno));return -1;}svcmgr_handle = svcmgr;binder_loop(bs, svcmgr_handler);return 0;}主要工作:1. 初始化binder,打開/dev/binder設備,在內存中為binder映射128Kb空間。bs = binder_open(128*1024);其中binder_open位于binder.c中,源代碼為:struct binder_state *binder_open(unsigned mapsize){struct binder_state *bs;bs = malloc(sizeof(*bs));if (!bs) {errno = ENOMEM;return 0;}bs->fd = open("/dev/binder", O_RDWR);……return 0;}2. 指定SM對于代理binder的handle為0,即client嘗試同SM通信時創建一個handle為0的代理binder。void *svcmgr = BINDER_SERVICE_MANAGER;svcmgr_handle = svcmgr;其中BINDER_SERVICE_MANAGER在binder.h中被指定為0:#define BINDER_SERVICE_MANAGER ((void*) 0)3. 通知binder driver(BD)使SM成為BD的context manager;if (binder_become_context_manager(bs)) {LOGE("cannot become context manager (%s)/n", strerror(errno));return -1;}binder_become_context_manager(bs)源碼位于binder.c中:int binder_become_context_manager(struct binder_state *bs){return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);}4.進入一個死循環,不斷讀取內核的binder driver,查看是否有對service的操作請求,如果有調用svcmgr_handler來處理請求操作:binder_loop(bs, svcmgr_handler);binder_loop(,)源碼位于binder.c中:void binder_loop(struct binder_state *bs, binder_handler func){int res;struct binder_write_read bwr;unsigned readbuf[32];……}}5.維護一個svclist列表來存儲service的信息。源碼位于service_manager.c:int svcmgr_handler(struct binder_state *bs,struct binder_txn *txn,struct binder_io *msg,struct binder_io *reply){struct svcinfo *si;……}

              • ProcessState

                ProcessState是每個進程在使用Binder通信時都需要維護的,用來描述當前進程的binder狀態。

                ProcessState主要完成兩個功能:

                1.創建一個thread負責與內核中的binder模塊進行通信(Poolthread)。

                在Binder IPC中,所有進程均會啟動一個thread來負責與binder來直接通信,也就是不斷讀寫binder,這個線程主體是一個IPCThreadState對象(具體介紹見第4節)。

                Poolthread啟動方式:ProcessState::self()->startThreadPool();/frameworks/native/libs/binder/ProcessState.cpp136void ProcessState::startThreadPool(){AutoMutex _l(mLock);` if (!mThreadPoolStarted) {mThreadPoolStarted = true;spawnPooledThread(true);}}

                2.為知道的handle創建一個BpBinder對象,并管理進程中所有的BpBinder對象。

                BpBinder在第一節已經提到,其主要功能是負責client向BD發送調用請求的數據,是client端binder通信的核心,通過調用transact向BD發送調用請求的數據。

                ProcessState通過如下函數獲取BpBinder對象:

                /frameworks/native/libs/binder/ProcessState.cppsp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller){return getStrongProxyForHandle(0);}sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle){sp<IBinder> result;AutoMutex _l(mLock);handle_entry* e = lookupHandleLocked(handle);……return result;}ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle){const size_t N=mHandleToObject.size();if (N <= (size_t)handle) {handle_entry e;e.binder = NULL;e.refs = NULL;status_t err = mHandleToObject.insertAt(e, N, handle+1-N);if (err < NO_ERROR) return NULL;}return &mHandleToObject.editItemAt(handle);}

                在獲取BpBinder對象的過程中,ProcessState會維護一個BpBinder的vecto:mHandleToObject(具體調用過程見上述源代碼)。

                創建一個BpBinder實例時,回去查詢mHandleToObject,如果對應的handler以及有binder指針,就不再創建,否則創建并插入到mHandlerToObject中(具體代碼見上述的lookupHandleLocked)。

                BpBinder構造函數位于/frameworks/native/libs/binder/BpBinder.cpp:

                BpBinder::BpBinder(int32_t handle): mHandle(handle), mAlive(1), mObitsSent(0), mObituaries(NULL){ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);extendObjectLifetime(OBJECT_LIFETIME_WEAK);IPCThreadState::self()->incWeakHandle(handle);}

                通過此構造函數我們可以發現:BpBinder會將通信中server的handle記錄下來。當有數據發送時,會把數據的發送目標通知BD。

              • IPCThreadState

                IPCThreadState也是一個單例模式,由上邊我們已知每個進程維護一個ProcessState實例,且ProcessState只啟動一個Pool thread,因此一個進程之后啟動一個Pool thread。

                IPCThreadState實際內容為:

                void IPCThreadState::joinThreadPool(bool isMain){LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); set_sched_policy(mMyThreadId, SP_FOREGROUND); status_t result;do {int32_t cmd;if (mIn.dataPosition() >= mIn.dataSize()) {size_t numPending = mPendingWeakDerefs.size();if (numPending > 0) {for (size_t i = 0; i < numPending; i++) {RefBase::weakref_type* refs = mPendingWeakDerefs[i];refs->decWeak(mProcess.get());}mPendingWeakDerefs.clear();}numPending = mPendingStrongDerefs.size();if (numPending > 0) {for (size_t i = 0; i < numPending; i++) {BBinder* obj = mPendingStrongDerefs[i];obj->decStrong(mProcess.get());}mPendingStrongDerefs.clear();}}result = talkWithDriver();if (result >= NO_ERROR) {size_t IN = mIn.dataAvail();if (IN < sizeof(int32_t)) continue;cmd = mIn.readInt32();IF_LOG_COMMANDS() {alog << "Processing top-level Command: "<< getReturnString(cmd) << endl;}result = executeCommand(cmd);}if(result == TIMED_OUT && !isMain) {break;}} while (result != -ECONNREFUSED && result != -EBADF);LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n",(void*)pthread_self(), getpid(), (void*)result);mOut.writeInt32(BC_EXIT_LOOPER);talkWithDriver(false);}

                ProcessState中有2個Parcel成員(mIn和mOut),由以上代碼可見,Pool Thread會不斷查詢BD中是否有數據可讀,若有,則保存在mIn;不停檢查mOut是否有數據需要向BD發送,若有,則寫入BD。

                根據第三節提到的:BpBinder通過調用transact向BD發送調用請求的數據,也就是說ProcessState中生成的BpBinder實例通過調用IPCThreadState的transact函數來向mOut中寫入數據,這樣的話這個binder IPC過程的client端的調用請求的發送過程就講述完畢。

                IPCThreadState有兩個重要的函數,talkWithDriver函數負責從BD讀寫數據,executeCommand函數負責解析并執行mIn中的數據。

              • 兩個接口類

                1.BpINTERFACE

                client在獲得server端service時,server端向client提供一個接口,client在這個接口基礎上創建一個BpINTERFACE,使用此對象,client端的應用能夠像本地調用一樣直接調用server端的方法,而不必關系binder IPC實現。

                BpINTERFACE原型如下:/frameworks/native/include/binder/IInterface.h template<typename INTERFACE>class BpInterface : public INTERFACE, public BpRefBase{public:BpInterface(const sp<IBinder>& remote);protected:virtual IBinder* onAsBinder();};

                可見,BpINTERFACE繼承自INTERFACE、BpRefBase。

                BpINTERFACE既實現了service中各方法的本地操作,將每個方法的參數以Parcel的形式發送給BD。同時又將BpBinder作為了自己的成員來管理,將BpBinder存儲在mRemote中,BpServiceManager通過調用BpRefBase的remote()來獲得BpBinder指針。

                2.BnINTERFACE

              同樣位于/frameworks/native/include/binder/IInterface.h template<typename INTERFACE>class BnInterface : public INTERFACE, public BBinder{public:virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);virtual const String16& getInterfaceDescriptor() const;protected:virtual IBinder* onAsBinder();};

              由代碼可知,BnInterface繼承自INTERFACE、BBinder。

              class BBinder : public

              IBinder,由此可見,server端的binder操作及狀態維護是通過BBinder來實現的。BBinder即為binder的本質。

              3.接口類總結

              由上節的描述及剛才對于兩個接口類源代碼分析可知:BpBinder是client端用于創建消息發送的機制,而BBinder是server端用于接口消息的通道。

              BpBinder是client創建的用于消息發送的代理,其transact函數用于向IPCThreadState發送消息,通知其有消息要發送給BD,部分源代碼如下:

              /frameworks/native/libs/binder/BpBinder.cpp status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {if (mAlive) {status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);if (status == DEAD_OBJECT) mAlive = 0;return status;}return DEAD_OBJECT;}default:return UNKNOWN_TRANSACTION;} }

              由BBinder的源碼可知,其作用是當IPCThreadState收到BD消息時,通過transact方法將其傳遞給它的子類BnSERVICE的onTransact函數執行server端的操作。部分源碼如下:

              /frameworks/native/libs/binder/Binder.cppstatus_t BBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){data.setDataPosition(0); status_t err = NO_ERROR;switch (code) {case PING_TRANSACTION:reply->writeInt32(pingBinder());break;default:err = onTransact(code, data, reply, flags);break;}if (reply != NULL) {reply->setDataPosition(0);}return err;}

              由上述可知,BpINTERFACE,BnINTERFACE均來自同一接口類IINTERFACE,由此保證了service方法在C/S兩端的一致性。

              • writeStrongBinder和readStrongBinder
            1. writeStrongBinder是client將一個binder傳送給server時需要調用的函數。

              具體源碼如下:status_t Parcel::writeStrongBinder(const sp<IBinder>& val){return flatten_binder(ProcessState::self(), val, this);}flatten_binder為:status_t flatten_binder(const sp<ProcessState>& proc,const sp<IBinder>& binder, Parcel* out){flat_binder_object obj;obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;if (binder != NULL) {IBinder *local = binder->localBinder();if (!local) {BpBinder *proxy = binder->remoteBinder();if (proxy == NULL) {LOGE("null proxy");}const int32_t handle = proxy ? proxy->handle() : 0;obj.type = BINDER_TYPE_HANDLE;obj.handle = handle;obj.cookie = NULL;} else {obj.type = BINDER_TYPE_BINDER;obj.binder = local->getWeakRefs();obj.cookie = local;}} else {obj.type = BINDER_TYPE_BINDER;obj.binder = NULL;obj.cookie = NULL;} return finish_flatten_binder(binder, obj, out);}

              下邊舉例說明,addService源碼為:

              /frameworks/native/libs/binder/IServiceManager.cppvirtual status_t addService(const String16& name, const sp<IBinder>& service,bool allowIsolated){Parcel data, reply;data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());data.writeString16(name);data.writeStrongBinder(service);data.writeInt32(allowIsolated ? 1 : 0);status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);return err == NO_ERROR ? reply.readExceptionCode() : err;}

              由上述代碼塊可知,寫入到parcel的binder類型為BINDER_TYPE_BINDER,然而SM收到的Service的binder類型必須為BINDER_TYPE_HANDLE才會將其添加到svclist中,因此說,addService開始傳遞的binder類型為BINDER_TYPE_BINDER然而SM收到的binder類型為BINDER_TYPE_HANDLE,中間經歷了一個改變,代碼如下:

              drivers/staging/android/Binder.cstatic void binder_transaction(struct binder_proc *proc,struct binder_thread *thread,struct binder_transaction_data *tr, int reply){……if (fp->type == BINDER_TYPE_BINDER)fp->type = BINDER_TYPE_HANDLE;elsefp->type = BINDER_TYPE_WEAK_HANDLE;fp->handle = ref->desc;……}

              由以上函數可知,SM只保存了Service binder的handle和name,當client需要和Service通信時,如何才能獲得Service得binder呢?需要由readStrongBinder來完成。

            2. readStrongBinder

              Client向server請求時,server向BD發送一個binder返回給SM(保存handle和name),當IPCThreadState收到由返回的parcel時,client通過這一函數將這個server返回給SM的binder讀出。

              源碼為:/frameworks/native/libs/binder/Parcel.cppsp<IBinder> Parcel::readStrongBinder() const{sp<IBinder> val;unflatten_binder(ProcessState::self(), *this, &val);return val;}unflatten_binder為:status_t unflatten_binder(const sp<ProcessState>& proc,const Parcel& in, sp<IBinder>* out){const flat_binder_object* flat = in.readObject(false);if (flat) {switch (flat->type) {case BINDER_TYPE_BINDER:*out = static_cast<IBinder*>(flat->cookie);return finish_unflatten_binder(NULL, *flat, in);case BINDER_TYPE_HANDLE:*out = proc->getStrongProxyForHandle(flat->handle);return finish_unflatten_binder(static_cast<BpBinder*>(out->get()), *flat, in);}}return BAD_TYPE;}

              由如上源碼可知:發現如果server返回的binder類型為BINDER_TYPE_BINDER的話,直接獲取這個binder;如果server返回的binder類型為BINDER_TYPE_HANDLE時,那么需要重新創建一個BpBinder返回給client。Client通過獲得SMhandle來重新構建代理binder與server進行通信。

            3. 至此,native通信機制已構建完畢。

              二、Java層的binder機制

              下邊來解析一下java層對于binder的封裝過程,分四部分來進行介紹:Java層ServiceManager的結構、如何注冊一個Service、如何得到一個Service、Service代理對象方法的過程。

              *ServiceManager的結構:

              在Java層,ServiceManager的函數源碼為:/frameworks/base/core/java/android/os/ServiceManager.javapublic final class ServiceManager {} public static IBinder getService(String name) {}public static void addService(String name, IBinder service) {}public static void addService(String name, IBinder service, boolean allowIsolated) {}public static IBinder checkService(String name) {}public static String[] listServices() throws RemoteException {}public static void initServiceCache(Map<String, IBinder> cache) {}

              由源碼可知,ServiceManager沒有繼承其他類,下邊我們來分析ServiceManager管理binder通信的流程。

              • 在Java層注冊Service:

                通過ServiceManager的addService()可注冊自己,其傳輸了兩個參數:String name, IBinder service,分別為name和BBinder的子類對象,跟native層ServiceManager中Service的注冊方法相一致。

                具體源碼如下:public static void addService(String name, IBinder service) {try {getIServiceManager().addService(name, service, false);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);}}

                getIServiceManager().addService表明將此操作請求轉發給了getIServiceManager(),返回一個IServiceManger類型的sServiceManager對象,源碼如下:

                private static IServiceManager getIServiceManager() {if (sServiceManager != null) {return sServiceManager;}sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());return sServiceManager;}

                BinderInternal.getContextObject在native層得到BpBinder對象。

                ServiceManagerNative.asInterface 將BpBinder封裝為Java層可用的ServiceManagerProxy對象。

                下面來通過源碼具體分析BpBinder封裝為ServiceManagerProxy的過程:

                static public IServiceManager asInterface(IBinder obj)

                {if (obj == null) {return null;}IServiceManager in =(IServiceManager)obj.queryLocalInterface(descriptor);if (in != null) {return in;}return new ServiceManagerProxy(obj);}

                由源碼可知,通過asInterface的轉換,BpBinder對象生成了ServiceManagerProxy對象。也就是說getIServiceManager()得到的是一個ServiceManagerProxy對象,那么ServiceManagerProxy又是什么,下邊來具體分析一下。

                class ServiceManagerProxy implements IServiceManager {public ServiceManagerProxy(IBinder remote) {mRemote = remote;}public IBinder asBinder() {return mRemote;}public IBinder getService(String name) throws RemoteException {}public IBinder checkService(String name) throws RemoteException {}public void addService(String name, IBinder service, boolean allowIsolated)throws RemoteException {}public String[] listServices() throws RemoteException {}public void setPermissionController(IPermissionController controller)throws RemoteException {}private IBinder mRemote;}

                由源碼可知,ServiceManagerProxy繼承自IServiceManager,提供add、get、list、check等方法。由以上分析可知,通過getIServiceManager的便可得到ServiceManagerProxy對象,調用其addService方法便可進行注冊,addService源碼如下:

                public void addService(String name, IBinder service, boolean allowIsolated)throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IServiceManager.descriptor);data.writeString(name);data.writeStrongBinder(service);data.writeInt(allowIsolated ? 1 : 0);mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);reply.recycle();data.recycle();}

                可知,將name和Service對象封裝到Parcel中,調用transact()方法送出,并將當前操作標記為ADD_SERVICE_TRANSACTION,根據上一章提到的內容,transact()便會調用到BpBinder中,此時便進入到native層的使用,這部分內容已經在上一章節分析完畢,具體流程圖如下:?

              • 客戶端得到一個Service:

                主要流程如下:通過Java層的ServerManager得到相應的Service,然后通過asInterface()將得到的對象轉為客戶端可直接調用的代理對象,然后調用代理對象的updateAdnRecordsEfBySearch()方法。

                具體分析如下:首先,通過ServerManager得到相應的BpBinder對象。源碼位于ServerManager.java中public static IBinder getService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {return getIServiceManager().getService(name);}} catch (RemoteException e) {Log.e(TAG, "error in getService", e);}return null;}可見,調用getIServiceManager()對象的getService()方法,代碼如下。private static IServiceManager getIServiceManager() {if (sServiceManager != null) {return sServiceManager;}// Find the service managersServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());return sServiceManager;}

              可知通過IServiceManager得到的是一個ServiceManager在Java層的代理對象,下邊來分析此代理對象的getService( )方法。

              /frameworks/base/core/java/android/os/ServiceManagerNative.javapublic IBinder getService(String name) throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IServiceManager.descriptor);data.writeString(name);mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);IBinder binder = reply.readStrongBinder();reply.recycle();data.recycle();return binder;}

              可見,getService請求被轉交給native層,由上一章分析可知,native層得到請求后會將目標Service的BpBinder返回給客戶端,得到BpBinder對象后,通過asInterface()得到一個Proxy對象,客戶端便通過這個代理類調用服務端定義的各種方法。具體客戶端得到Service的流程圖如下:?

              三、總結

              Binder通信整體流程圖如下:


              原文地址:https://mobile100.gitbooks.io/android/content/paper/android_binderji_523628_1501210451_zhang_zhi_5eb72.html

              總結

              以上是生活随笔為你收集整理的Android Binder机制(1501210451 张志康)的全部內容,希望文章能夠幫你解決所遇到的問題。

              如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。