android進(jìn)程間通訊(2)--Binder解析及AIDL的使用

android進(jìn)程間通訊(2)–理解Binder及AIDL使用

前言:之前一篇文章記錄了Bundle和文件共享的方式來進(jìn)行進(jìn)程間通訊,但并不是所有場景都適用的元咙,比如A進(jìn)程正在進(jìn)行一個(gè)計(jì)算,計(jì)算完成后要啟動B進(jìn)程并把計(jì)算結(jié)果傳遞給B進(jìn)程浸须,但是計(jì)算結(jié)果不支持放入Bundle响蓉,又或者A進(jìn)程有個(gè)封裝好的方法,B進(jìn)程想要調(diào)用A進(jìn)程里面的方法,使用Bundle則行不通了替梨。因此android提供了一種進(jìn)程間通訊方式Binder。Binder是Android系統(tǒng)最主要的IPC方式装黑,其中Messenger副瀑,AIDL,ContentProvider底層實(shí)現(xiàn)都是Binder恋谭。由于Binder的實(shí)現(xiàn)比較復(fù)雜糠睡,這里只記錄基本原理。

1.Binder機(jī)制

了解binder首先要解決幾個(gè)疑問:1.什么是Binder疚颊? 2.Binder的實(shí)現(xiàn)原理狈孔?3.Binder的具體應(yīng)用有哪些?

(1).什么是binder

直觀來說材义,Binder是android中的一個(gè)類均抽,它實(shí)現(xiàn)了IBinder接口。從IPC角度說其掂,Binder是android中的一種跨進(jìn)程通訊方式油挥。Binder可以理解為一種虛擬的物理設(shè)備,它的設(shè)備驅(qū)動是/dev/binder款熬,該通訊的方式在Linux中沒有深寥。從Android Framework角度來說,Binder是ServiceManager連接各種Manager比如ActivityManager贤牛,WindowManager翩迈,InputManager,ResourceManager等等和相應(yīng)的ManagerService的橋梁盔夜。從安卓應(yīng)用層來說,Binder是客戶端和服務(wù)端進(jìn)行通訊的媒介。

(2).Binder實(shí)現(xiàn)原理

個(gè)人覺得想要理解Binder的實(shí)現(xiàn)原理喂链,首先要理解以下兩個(gè)方面的東西返十。1.Android的體系架構(gòu);2.計(jì)算機(jī)的內(nèi)存管理椭微。

<1>.Android體系架構(gòu)

首先來看一下android架構(gòu)圖洞坑,圖片來自網(wǎng)絡(luò)。


image

1.內(nèi)核層:Linux 內(nèi)核和各類硬件設(shè)備的驅(qū)動蝇率,binder驅(qū)動/dev/binder位于這一層
2.類庫層:由于類庫層多是c/c++編寫的native代碼迟杂,所以又叫C庫層
3.應(yīng)用程序框架層:這一層可以理解為 Android SDK,提供四大組件本慕,View 繪制體系等平時(shí)開發(fā)中用到的基礎(chǔ)部件排拷,因?yàn)樵搶又饕莏ava編寫,所以又叫java庫層
4.應(yīng)用層:開發(fā)人員開發(fā)的應(yīng)用程序?qū)?br> 其實(shí)在內(nèi)核層和類庫層還有一層是HAL锅尘,硬件抽象層:封裝「內(nèi)核層」硬件驅(qū)動监氢,提供可供「系統(tǒng)服務(wù)層」調(diào)用的統(tǒng)一硬件接口

<2>計(jì)算機(jī)內(nèi)存管理

1.早期的機(jī)器并沒有任何的虛擬地址的概念,被稱為“實(shí)模式”內(nèi)存管理藤违。而后期發(fā)展出來的設(shè)備提供了虛擬地址的硬件實(shí)現(xiàn)浪腐。最早的操作系統(tǒng)中,并沒有嚴(yán)格意義的內(nèi)存保護(hù)機(jī)制顿乒,對于內(nèi)存的訪問約束完全在于程序編寫者的自覺性议街,這種做法并不靠譜。為了管理內(nèi)存和保護(hù)內(nèi)存璧榄,提出了虛擬內(nèi)存和進(jìn)程概念特漩。虛擬內(nèi)存是一個(gè)抽象的概念,它為每個(gè)進(jìn)程提供了一個(gè)假象犹菱,即每個(gè)進(jìn)程都在獨(dú)占的使用主存拾稳,每個(gè)進(jìn)程看到的內(nèi)存都是一致的,稱為虛擬地址空間腊脱。如下圖所示访得,在Linux中,地址空間的最上面區(qū)域是保留給操作系統(tǒng)的代碼和數(shù)據(jù)的陕凹,這對所有進(jìn)程來說都一樣悍抑,地址空間的底部區(qū)域存放用戶進(jìn)程定義的代碼和數(shù)據(jù)。


VmYUGfo.png

也正是因?yàn)檫@樣杜耙,每個(gè)進(jìn)程都有自己獨(dú)立的內(nèi)存空間搜骡,沒有辦法直接訪問它管轄以外的內(nèi)存空間,所以進(jìn)程間通訊要通過系統(tǒng)提供的IPC方式進(jìn)行通訊佑女。而Binder則是android上主要的IPC方式记靡。

從內(nèi)存訪問的角度來看谈竿,Binder的作用就是讓兩個(gè)進(jìn)程可以訪問同一塊內(nèi)存空間,實(shí)現(xiàn)數(shù)據(jù)交換摸吠,如圖:圖片來自http://gityuan.com/2015/10/31/binder-prepare/

C0ddZIP.png

每個(gè)Android的進(jìn)程空凸,只能運(yùn)行在自己進(jìn)程所擁有的虛擬地址空間。對應(yīng)一個(gè)4GB的虛擬地址空間寸痢,其中3GB是用戶空間呀洲,1GB是內(nèi)核空間,當(dāng)然內(nèi)核空間的大小是可以通過參數(shù)配置調(diào)整的啼止。對于用戶空間道逗,不同進(jìn)程之間彼此是不能共享的,而內(nèi)核空間卻是可共享的献烦。Client進(jìn)程向Server進(jìn)程通信滓窍,恰恰是利用進(jìn)程間可共享的內(nèi)核內(nèi)存空間來完成底層通信工作的,Client端與Server端進(jìn)程往往采用ioctl等方法跟內(nèi)核空間的驅(qū)動進(jìn)行交互

<3>Binder實(shí)現(xiàn)機(jī)制

Android系統(tǒng)Binder機(jī)制中的四個(gè)組件Client仿荆、Server贰您、Service Manager和Binder驅(qū)動程序的關(guān)系如下圖所示:


image

1. Client、Server和Service Manager實(shí)現(xiàn)在用戶空間中拢操,Binder驅(qū)動程序?qū)崿F(xiàn)在內(nèi)核空間中
2. Binder驅(qū)動程序和Service Manager在Android平臺中已經(jīng)實(shí)現(xiàn)锦亦,開發(fā)者只需要在用戶空間實(shí)現(xiàn)自己的Client和Server
3. Binder驅(qū)動程序提供設(shè)備文件/dev/binder與用戶空間交互,Client令境、Server和Service Manager通過open和ioctl文件操作函數(shù)與Binder驅(qū)動程序進(jìn)行通信
4. Client和Server之間的進(jìn)程間通信通過Binder驅(qū)動程序間接實(shí)現(xiàn)
5. Service Manager是一個(gè)守護(hù)進(jìn)程杠园,用來管理Server,并向Client提供查詢Server接口的能力

2.Binder具體應(yīng)用

從Binder的實(shí)現(xiàn)機(jī)制可以知道舔庶,使用Binder需要?jiǎng)?chuàng)建Client(客戶端)和Server(服務(wù)端)抛蚁。應(yīng)用層使用Binder進(jìn)行進(jìn)程間通訊具體實(shí)現(xiàn)有Messenger,AIDL惕橙,ContentProvider瞧甩,由于Messenger底層是AIDL,Contentprovider涉及到數(shù)據(jù)庫弥鹦。這里只記錄AIDL的使用方式肚逸。

服務(wù)端創(chuàng)建:
步驟1.首先新建一個(gè)工程,并在app的module的mian文件下創(chuàng)建文件夾aidl彬坏,如圖:


image

步驟2:創(chuàng)建.aidl文件朦促,如圖中的hdcPearAIDL.aidl文件,并添加兩個(gè)方法栓始,hdcPearAIDL.aidl內(nèi)容如下:

 package pear.cn.hdcsdktest;
   interface hdcPearAIDL {
        void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
           double aDouble, String aString);
        int add(int a,int b);
        void shellCommand(String cmd);
    }

build項(xiàng)目之后會在build>generated->source->aidl->debug->下面生成hdcPearAIDL的java文件务冕,這文件是系統(tǒng)自動生成的,如下圖:


DjISWbB.png

步驟3.創(chuàng)建服務(wù)并注冊幻赚,如下圖:

image

服務(wù)內(nèi)容如下,AidlService繼承Service禀忆,重寫onBind()方法臊旭,并返回IBinder的實(shí)例。并在iBinder里面實(shí)現(xiàn)接口定義的方法油湖,提供給其他進(jìn)程調(diào)用巍扛。

/**
   * Created by hdc on 2016/11/28.
   *
   */

    public class AidlService extends Service {
        @Nullable
        @Override
     public IBinder onBind(Intent intent) {
            return iBinder;
    }
    private IBinder iBinder = new hdcPearAIDL.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean,
         float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public int add(int a, int b) throws RemoteException {
            LogUtil.i("hdcTest"," use the method "+a+"/"+b);
            return a+b;
        }

        @Override
        public void shellCommand(String cmd) throws RemoteException {
            LogUtil.i("hdcTest"," use the method shellCommand "+cmd);
            ShellUtil.execCommand(cmd,ShellUtil.checkSuRoot());
        }
    };
}

別忘記在AndroidManifest中注冊AidlService。

    <service android:name=".services.AidlService">
        <intent-filter>
            <action android:name="pear.cn.hdcsdktest.services.AidlService"/>
        </intent-filter>
     </service>

客戶端創(chuàng)建:
步驟1:同樣在app的module的mian文件夾下面創(chuàng)建aidl文件夾和相同包名乏德,相同名字的aidl文件,可以將服務(wù)端的aidl文件直接copy過來吠昭,如下圖:


image

步驟2:綁定服務(wù)喊括,在客戶端的activity的onCreate方法里面綁定服務(wù),在onServiceConnected()方法返回hdcPearAIDL對象,可以使用aidl對象來調(diào)用服務(wù)端的方法矢棚。

 public class MainActivity extends AppCompatActivity {

    private hdcPearAIDL aidl;

    private ServiceConnection serviceConnection =new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            aidl= hdcPearAIDL.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            aidl=null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService();
    }

    private void bindService() {

        Intent intent = new Intent();
        //綁定服務(wù)端的service
        intent.setAction("pear.cn.hdcsdktest.services.AidlService");
        //新版本(5.0后)必須顯式intent啟動 綁定服務(wù)
        intent.setComponent(new ComponentName("pear.cn.hdcsdktest","pear.cn.hdcsdktest.services.AidlService"));
        //綁定的時(shí)候服務(wù)端自動創(chuàng)建
        bindService(intent,serviceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(serviceConnection);
    }
}

總結(jié)

1.Binder是android中最主要的IPC方式
2.Binder實(shí)現(xiàn)原理涉及到android框架體系以及操作系統(tǒng)的內(nèi)存管理機(jī)制
3.Messager郑什,AIDL,ContentProvider的底層原理是Binder

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蒲肋,隨后出現(xiàn)的幾起案子蘑拯,更是在濱河造成了極大的恐慌,老刑警劉巖兜粘,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件申窘,死亡現(xiàn)場離奇詭異,居然都是意外死亡孔轴,警方通過查閱死者的電腦和手機(jī)剃法,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來路鹰,“玉大人贷洲,你說我怎么就攤上這事〗” “怎么了优构?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長雁竞。 經(jīng)常有香客問我钦椭,道長,這世上最難降的妖魔是什么浓领? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任玉凯,我火速辦了婚禮,結(jié)果婚禮上联贩,老公的妹妹穿的比我還像新娘漫仆。我一直安慰自己,他們只是感情好泪幌,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布盲厌。 她就那樣靜靜地躺著署照,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吗浩。 梳的紋絲不亂的頭發(fā)上建芙,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機(jī)與錄音懂扼,去河邊找鬼禁荸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛阀湿,可吹牛的內(nèi)容都是我干的赶熟。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼陷嘴,長吁一口氣:“原來是場噩夢啊……” “哼映砖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起灾挨,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤邑退,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后劳澄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體地技,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年浴骂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乓土。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡溯警,死狀恐怖趣苏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情梯轻,我是刑警寧澤食磕,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站喳挑,受9級特大地震影響彬伦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜伊诵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一单绑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧曹宴,春花似錦搂橙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽苔巨。三九已至,卻和暖如春废离,著一層夾襖步出監(jiān)牢的瞬間侄泽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工蜻韭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悼尾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓肖方,卻偏偏與公主長得像诀豁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子窥妇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,524評論 25 707
  • Android跨進(jìn)程通信IPC整體內(nèi)容如下 1、Android跨進(jìn)程通信IPC之1——Linux基礎(chǔ)2娩践、Andro...
    隔壁老李頭閱讀 11,823評論 11 56
  • 逆位星幣3活翩,讀牌1、我是那個(gè)站在凳子上的人翻伺,其他兩個(gè)人在挑我的毛病材泄,這是我的第一感覺,就像我平時(shí)的狀態(tài)吨岭,在面對這種...
    塔羅師默默閱讀 172評論 0 0
  • 一個(gè)人的奮斗應(yīng)該是這樣的 你有過拿自己和別人做比較拉宗,然后感到慌張、惆悵嗎辣辫?你有過把自己最寶貴的時(shí)間浪費(fèi)在錯(cuò)誤的人身...
    水哥1022閱讀 338評論 0 0
  • “老師旦事,出上海了嗎……?” “老師急灭,到浙江了敖愀 ?……” 對于這群嘰嘰喳喳的孩子們而言葬馋,一路抑制不住的興奮和激動卖鲤。是...
    陽光Sunflower閱讀 450評論 0 4