欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android10?Binder原理概述深入解析

 更新時(shí)間:2022年10月12日 10:53:45   作者:格子里的夢  
這篇文章主要為大家介紹了Android10?Binder原理概述深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

IPC工具介紹

Binder作為Android 眾多的IPC通訊手段之一,在Framework的數(shù)據(jù)傳輸中起到極為關(guān)鍵的作用。為什么Google需要重新創(chuàng)造Binder這么一個(gè)IPC工具,使用linux默認(rèn)提供的Pipe、Socket、共享內(nèi)存、信號、消息隊(duì)列等IPC工具不行嗎?

答案是 這些傳統(tǒng)的linux IPC工具有一部分android也在使用,只是在某些場合下它們無法滿足需求,所以才創(chuàng)造了Binder這么一個(gè)工具。 為了更好地向各位讀者解釋為什么需要Binder,我們先來簡單地認(rèn)識一下linux傳統(tǒng)的IPC工具,讓大家對它們的優(yōu)勢和劣勢有一個(gè)更為直觀的認(rèn)識。

Pipe

管道是一種最基本的IPC工具,作用于有血緣關(guān)系的進(jìn)程之間,完成數(shù)據(jù)傳遞。調(diào)用pipe系統(tǒng)函數(shù)即可創(chuàng)建一個(gè)管道。它有如下特質(zhì):

  • 其本質(zhì)是一個(gè)偽文件(實(shí)為內(nèi)核緩沖區(qū))
  • 由兩個(gè)文件描述符引用,一個(gè)表示讀端,一個(gè)表示寫端。
  • 規(guī)定數(shù)據(jù)從管道的寫端流入管道,從讀端流出,一般只能單向通信,雙向通信需建立兩個(gè)管道。
  • 只能用于父子、兄弟進(jìn)程(有共同祖先)間通信。
  • 數(shù)據(jù)一旦被讀走,便不在管道中存在,不可反復(fù)讀取。 因此,管道的局限性表現(xiàn)得非常明顯,它并不適合一對多的方式建立通訊(盡管技術(shù)上能夠?qū)崿F(xiàn)),原因在于第5條,管道中的數(shù)據(jù)無法反復(fù)讀取。類似的還有FIFO(命名管道),它在管道的基礎(chǔ)上做了升級,擺脫了第4條的共同祖先的限制,但仍要面臨一對多通訊的困境。

framework中有沒有使用Pipe進(jìn)行通訊?答案是有,但是用的很少,相比之下用的更多的是FIFO??!各位讀者如果感興趣的話,可以在源碼中搜一下 TransferPipe這個(gè)類,在其中可以找到Pipe的痕跡。

Sign

信號是由用戶、系統(tǒng)或者進(jìn)程發(fā)送給目標(biāo)進(jìn)程的信息,以通知目標(biāo)進(jìn)程某個(gè)狀態(tài)的改變或系統(tǒng)異常。linux系統(tǒng)已經(jīng)預(yù)置了一部分信號標(biāo)識,它們都有著特殊的含義,部分信號如下所示:

  • SIGHUP:本信號在用戶終端結(jié)束時(shí)發(fā)出,通常是在終端的控制進(jìn)程結(jié)束時(shí),通知同一會話期內(nèi)的各個(gè)作業(yè),這時(shí)他們與控制終端不在關(guān)聯(lián)。比如,登錄Linux時(shí),系統(tǒng)會自動(dòng)分配給登錄用戶一個(gè)控制終端,在這個(gè)終端運(yùn)行的所有程序,包括前臺和后臺進(jìn)程組,一般都屬于同一個(gè)會話。當(dāng)用戶退出時(shí),所有進(jìn)程組都將收到該信號,這個(gè)信號的默認(rèn)操作是終止進(jìn)程。此外對于與終端脫離關(guān)系的守護(hù)進(jìn)程,這個(gè)信號用于通知它重新讀取配置文件。
  • SIGINT:程序終止信號。當(dāng)用戶按下CRTL+C時(shí)通知前臺進(jìn)程組終止進(jìn)程。
  • SIGQUIT:Ctrl+\控制,進(jìn)程收到該信號退出時(shí)會產(chǎn)生core文件,類似于程序錯(cuò)誤信號。
  • SIGILL:執(zhí)行了非法指令。通常是因?yàn)榭蓤?zhí)行文件本身出現(xiàn)錯(cuò)誤,或者數(shù)據(jù)段、堆棧溢出時(shí)也有可能產(chǎn)生這個(gè)信號。
  • SIGTRAP:由斷點(diǎn)指令或其他陷進(jìn)指令產(chǎn)生,由調(diào)試器使用。
  • SIGABRT:調(diào)用abort函數(shù)產(chǎn)生,將會使程序非正常結(jié)束。
  • SIGBUS:非法地址。包括內(nèi)存地址對齊出錯(cuò)。比如訪問一個(gè)4個(gè)字長的整數(shù),但其地址不是4的倍數(shù)。它與SIGSEGV的區(qū)別在于后者是由于對合法地址的非法訪問觸發(fā)。
  • SIGFPE:發(fā)生致命的算術(shù)運(yùn)算錯(cuò)誤。
  • SIGKILL:用來立即結(jié)束程序的運(yùn)行。不能被捕捉、阻塞或忽略,只能執(zhí)行默認(rèn)動(dòng)作。

信號只能起到對進(jìn)程的通知作用,它無法發(fā)送復(fù)雜的數(shù)據(jù)類型,不適合用于進(jìn)程間的數(shù)據(jù)交換。

信號在整個(gè)framework中也扮演了極為重要的角色,各位讀者可以通過搜索sigemptyset、sigaddset等關(guān)鍵字,在源碼中找到它們的身影。

message queue

消息隊(duì)列,Unix的通信機(jī)制之一,可以理解為是一個(gè)存放消息(數(shù)據(jù))容器。將消息寫入消息隊(duì)列,然后再從消息隊(duì)列中取消息,一般來說是先進(jìn)先出的順序。消息隊(duì)列本質(zhì)上是位于內(nèi)核空間的鏈表,鏈表的每個(gè)節(jié)點(diǎn)都是一條消息。每一條消息都有自己的消息類型,消息類型用整數(shù)來表示,而且必須大于 0。每種類型的消息都被對應(yīng)的鏈表所維護(hù)。

其中數(shù)字 1 表示類型為 1 的消息,數(shù)字2、3、4 類似。彩色塊表示消息數(shù)據(jù),它們被掛在對應(yīng)類型的鏈表上。

消息隊(duì)列的缺陷在于:容量受到系統(tǒng)限制;消息隊(duì)列的發(fā)送方與接收方?jīng)]有強(qiáng)關(guān)聯(lián)性,容易造成發(fā)送方往消息隊(duì)列中存放了消息,沒有接收方來取消息或接收方?jīng)]有及時(shí)取消息的問題,消息的及時(shí)性無法保障。

目前在Android 10的非內(nèi)核源碼范圍內(nèi),沒有發(fā)現(xiàn)使用消息隊(duì)列。

shared memory

共享內(nèi)存就是映射一段能被其他進(jìn)程所訪問的內(nèi)存,這段共享內(nèi)存由一個(gè)進(jìn)程創(chuàng)建,但多個(gè)進(jìn)程都可以訪問。共享內(nèi)存是最快的 IPC 方式,它是針對其他進(jìn)程間通信方式運(yùn)行效率低而專門設(shè)計(jì)的。它往往與其他通信機(jī)制,如信號量,配合使用,來實(shí)現(xiàn)進(jìn)程間的同步和通信。

共享內(nèi)存利用內(nèi)存緩沖區(qū)直接交換信息,無須復(fù)制,快捷、信息量大是其優(yōu)點(diǎn)。但是共享內(nèi)存的通信方式是通過將共享的內(nèi)存緩沖區(qū)直接附加到進(jìn)程的虛擬地址空間中來實(shí)現(xiàn)的,因此,這些進(jìn)程之間的讀寫操作的同步問題操作系統(tǒng)無法實(shí)現(xiàn)。必須由各進(jìn)程利用其他同步工具解決,開發(fā)上手難度較高,容易出錯(cuò),且存在數(shù)據(jù)安全隱患。

目前在Android 10的非內(nèi)核源碼范圍內(nèi),沒有發(fā)現(xiàn)使用共享內(nèi)存。

Socket

Socket這個(gè)不需要特別介紹了,不管是做C++開發(fā)還是Java開發(fā),都會涉及到套接字編程。相對其他的IPC方式,Socket是最適合做一對多這種通訊需求的。它的問題在于數(shù)據(jù)需要經(jīng)過兩次拷貝,通訊效率相對低下。這個(gè)問題在電腦等設(shè)備上都不是什么特別大的問題,但考慮到Android搭載的移動(dòng)設(shè)備,尤其是早期的移動(dòng)設(shè)備,這個(gè)問題就很致命了。

framework中當(dāng)然也存在Socket的使用痕跡,比如 system/core/init/init.cpp這個(gè)文件中就采用epoll機(jī)制,實(shí)現(xiàn)init進(jìn)程與其子進(jìn)程的通訊。

Android更看重的是效率和一對多通訊的問題,無法采用傳統(tǒng)的IPC工具實(shí)現(xiàn),所以只能考慮自己另起爐灶。除此之外,傳統(tǒng)的IPC無法獲得對方進(jìn)程的PID\UID,從而無法鑒別對象的身份,從而會使Android系統(tǒng)的安全性無法得到保證(ps:無法獲得對方進(jìn)程的身份指的是Linux默認(rèn)沒有提供獲取通訊進(jìn)程的身份的接口,并不是說采用傳統(tǒng)IPC沒有辦法實(shí)現(xiàn)這樣的安全管控需求,只是谷歌在綜合考慮了上述所有的因素的情況下,在共享內(nèi)存的基礎(chǔ)上做了一套新的解決方案)。

這里給各位讀者留個(gè)思考題,有興趣的讀者可以自己動(dòng)手去實(shí)驗(yàn)一下:

在一對多通訊的場景下,Binder的傳輸效率一定會比Socket高嗎?(提示:Socket包括BIO、NIO、NIO2、epoll等,請不要局限在BIO的通訊方式)

AIDL

AIDL 是 Android interface definition Language 的英文縮寫, 意思Android 接口定義語言,它與Binder有著千絲萬縷的聯(lián)系。

AIDL是谷歌使用Java 編程語言的語法定義的專門服務(wù)于Binder IPC通訊的腳本語言,推出的根本原因是為了避免Binder通訊中大量模板代碼的書寫。AIDL腳本會在編譯期間,由Android SDK 工具生成基于該 .aidl 文件的 IBinder 接口,并將其保存到項(xiàng)目的 generated/ 目錄中。

我們來看一個(gè)簡單的aidl文件:

packageackage com.example.commonservice;
// Declare any non-default types here with import statements
interface ITtsService {
   void showTts(in String uid,in int textId,in boolean toPlayTts,in int type);
   boolean isShowing();
}

它生成的java文件如下所示:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 */
package com.example.commonservice;
// Declare any non-default types here with import statements
public interface ITtsService extends android.os.IInterface
{
  /** Default implementation for ITtsService. */
  public static class Default implements com.example.commonservice.ITtsService
  {
    @Override public void showTts(java.lang.String uid, int textId, boolean toPlayTts, int type) throws android.os.RemoteException
    {
    }
    @Override public boolean isShowing() throws android.os.RemoteException
    {
      return false;
    }
    @Override
    public android.os.IBinder asBinder() {
      return null;
    }
  }
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements com.example.commonservice.ITtsService
  {
    private static final java.lang.String DESCRIPTOR = "com.example.commonservice.ITtsService";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an com.example.commonservice.ITtsService interface,
     * generating a proxy if needed.
     */
    public static com.example.commonservice.ITtsService asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.example.commonservice.ITtsService))) {
        return ((com.example.commonservice.ITtsService)iin);
      }
      return new com.example.commonservice.ITtsService.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
    {
      java.lang.String descriptor = DESCRIPTOR;
      switch (code)
      {
        case INTERFACE_TRANSACTION:
        {
          reply.writeString(descriptor);
          return true;
        }
        case TRANSACTION_showTts:
        {
          data.enforceInterface(descriptor);
          java.lang.String _arg0;
          _arg0 = data.readString();
          int _arg1;
          _arg1 = data.readInt();
          boolean _arg2;
          _arg2 = (0!=data.readInt());
          int _arg3;
          _arg3 = data.readInt();
          this.showTts(_arg0, _arg1, _arg2, _arg3);
          reply.writeNoException();
          return true;
        }
        case TRANSACTION_isShowing:
        {
          data.enforceInterface(descriptor);
          boolean _result = this.isShowing();
          reply.writeNoException();
          reply.writeInt(((_result)?(1):(0)));
          return true;
        }
        default:
        {
          return super.onTransact(code, data, reply, flags);
        }
      }
    }
    private static class Proxy implements com.example.commonservice.ITtsService
    {
      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 void showTts(java.lang.String uid, int textId, boolean toPlayTts, int type) 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.writeString(uid);
          _data.writeInt(textId);
          _data.writeInt(((toPlayTts)?(1):(0)));
          _data.writeInt(type);
          boolean _status = mRemote.transact(Stub.TRANSACTION_showTts, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().showTts(uid, textId, toPlayTts, type);
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }
      @Override public boolean isShowing() throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        boolean _result;
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          boolean _status = mRemote.transact(Stub.TRANSACTION_isShowing, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            return getDefaultImpl().isShowing();
          }
          _reply.readException();
          _result = (0!=_reply.readInt());
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }
      public static com.example.commonservice.ITtsService sDefaultImpl;
    }
    static final int TRANSACTION_showTts = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_isShowing = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    public static boolean setDefaultImpl(com.example.commonservice.ITtsService impl) {
      if (Stub.Proxy.sDefaultImpl == null && impl != null) {
        Stub.Proxy.sDefaultImpl = impl;
        return true;
      }
      return false;
    }
    public static com.example.commonservice.ITtsService getDefaultImpl() {
      return Stub.Proxy.sDefaultImpl;
    }
  }
  public void showTts(java.lang.String uid, int textId, boolean toPlayTts, int type) throws android.os.RemoteException;
  public boolean isShowing() throws android.os.RemoteException;
}

雖然是簡短的一個(gè)aidl文件,但生成的模板代碼卻極為復(fù)雜,為了整理清楚這段代碼的結(jié)構(gòu),筆者先隱藏其部分內(nèi)容:

public interface ITtsService extends android.os.IInterface
{
    /** Default implementation for ITtsService. */
    public static class Default implements com.example.commonservice.ITtsService
    {
    }
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.example.commonservice.ITtsService
    {
        private static class Proxy implements com.example.commonservice.ITtsService
        {
        }
        static final int TRANSACTION_showTts = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_isShowing = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }
    public void showTts(java.lang.String uid, int textId, boolean toPlayTts, int type) throws android.os.RemoteException;
    public boolean isShowing() throws android.os.RemoteException;
}

可以看到,代碼的結(jié)構(gòu)如同套娃一樣,一層接一層。各位讀者不妨思考一下,如果不這樣套娃,把ITtsService里的DefaultStub類移到外面來,這樣做可不可以?

答案是,可以的,不過類的命名方式可能要稍微做一下修改,如ITtsService_Defalut、ITtsService_Stub,以便于引用上的區(qū)分。當(dāng)然,代碼的結(jié)構(gòu)不是重點(diǎn),雖然谷歌的方式可讀性會差一點(diǎn),但開發(fā)人員不需要直接和這些源碼打交道,也不是不可以接受。

Binder不一定都是跨進(jìn)程通訊,同樣也支持同進(jìn)程通訊,比如 Activity綁定Service,通過Binder實(shí)現(xiàn)數(shù)據(jù)傳輸。在同一進(jìn)程通訊的情況下,Stub類身兼兩職,因其implements了ITtsService,它可以作為客戶端的調(diào)用方;同時(shí),它也是服務(wù)端的實(shí)現(xiàn)方。而在跨進(jìn)程通訊的情況下,則由Proxy來擔(dān)任客戶端的調(diào)用方。

至于Default這個(gè)類的作用,暫時(shí)不明,無法找到相關(guān)的資料得知為什么谷歌要生成這么一個(gè)類。

在此,AIDL的介紹先告一段落,其中更多的細(xì)節(jié)將放到后續(xù)的文章中再做補(bǔ)充。

HIDL

HIDL的生命周期及其短暫,它從Android 8引入,然后在Android 10 立馬被 Stable AIDL 所取代,雖然沒啥存在感,但還是簡單地提及一下吧。

HAL 接口定義語言(簡稱 HIDL,發(fā)音為“hide-l”)是用于指定 HAL 和其用戶之間的接口的一種接口描述語言 (IDL)。HIDL 允許指定類型和方法調(diào)用(會匯集到接口和軟件包中)。從更廣泛的意義上來說,HIDL 是指用于在可以獨(dú)立編譯的代碼庫之間進(jìn)行通信的系統(tǒng)。

HIDL 旨在用于進(jìn)程間通信 (IPC)。進(jìn)程之間的通信采用 Binder 機(jī)制。對于必須與進(jìn)程相關(guān)聯(lián)的代碼庫,還可以使用直通模式(在 Java 中不受支持)。

更多HIDL相關(guān)的資料,可以參考 source.android.google.cn/docs/core/a…

以上就是Android10 Binder原理概述深入解析的詳細(xì)內(nèi)容,更多關(guān)于Android10 Binder原理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • LayoutAnimation給ListView中的item設(shè)置動(dòng)態(tài)出場效果(實(shí)例)

    LayoutAnimation給ListView中的item設(shè)置動(dòng)態(tài)出場效果(實(shí)例)

    下面小編就為大家?guī)硪黄狶ayoutAnimation給ListView中的item設(shè)置動(dòng)態(tài)出場效果(實(shí)例)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • Android SDK中的Support兼容包詳解

    Android SDK中的Support兼容包詳解

    這篇文章主要介紹了Android SDK中的Support兼容包詳解,本文詳細(xì)區(qū)分了Support Library的版本區(qū)別、各種Theme的概念和使用注意事項(xiàng)等內(nèi)容,需要的朋友可以參考下
    2015-05-05
  • 詳談OnTouchListener與OnGestureListener的區(qū)別

    詳談OnTouchListener與OnGestureListener的區(qū)別

    下面小編就為大家?guī)硪黄斦凮nTouchListener與OnGestureListener的區(qū)別。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • Android Studio常用快捷鍵功能說明

    Android Studio常用快捷鍵功能說明

    本文給大家收藏整理了關(guān)于Android Studio常用快捷鍵功能說明,需要的朋友可以參考下
    2017-10-10
  • Android仿QQ復(fù)制昵稱效果

    Android仿QQ復(fù)制昵稱效果

    這幾天做一個(gè)復(fù)制文本的需求,突然看到QQ上復(fù)制昵稱跟QQ號的效果,覺得很不錯(cuò),就想要模仿一波,辦法比較簡單粗暴,反編譯QQ獲取了那個(gè).9圖片,然后就是用PopWindow實(shí)現(xiàn)了,需要的朋友可以參考下
    2019-05-05
  • Android開發(fā)實(shí)現(xiàn)自動(dòng)切換文字TextSwitcher功能示例

    Android開發(fā)實(shí)現(xiàn)自動(dòng)切換文字TextSwitcher功能示例

    這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)自動(dòng)切換文字TextSwitcher功能,結(jié)合實(shí)例形式詳細(xì)分析了Android使用TextSwitcher實(shí)現(xiàn)文字自動(dòng)切換的原理、實(shí)現(xiàn)方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2019-03-03
  • Android實(shí)現(xiàn)語音識別代碼

    Android實(shí)現(xiàn)語音識別代碼

    語音識別在android上使用起來很方便也很簡單.但是有個(gè)前提條件,就是android機(jī)器上必須預(yù)先安裝google的語音搜索工具,今天我們就來詳細(xì)探討下
    2015-06-06
  • Android自定義仿微信PopupWindow效果

    Android自定義仿微信PopupWindow效果

    這篇文章主要為大家詳細(xì)介紹了Android自定義仿微信PopupWindow效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android Viewpager實(shí)現(xiàn)無限循環(huán)輪播圖

    Android Viewpager實(shí)現(xiàn)無限循環(huán)輪播圖

    這篇文章主要為大家詳細(xì)介紹了Android Viewpager實(shí)現(xiàn)無限循環(huán)輪播圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Android組件Activity的啟動(dòng)過程深入分析

    Android組件Activity的啟動(dòng)過程深入分析

    這篇文章主要介紹了Android組件Activity的啟動(dòng)過程,Activity作為Android四大組件之一,他的啟動(dòng)沒有那么簡單。這里涉及到了系統(tǒng)服務(wù)進(jìn)程,啟動(dòng)過程細(xì)節(jié)很多,這里我只展示主體流程。activity的啟動(dòng)流程隨著版本的更替,代碼細(xì)節(jié)一直在進(jìn)行更改,每次都會有很大的修改
    2023-04-04

最新評論