Read The Fucking Source Code
0. 準(zhǔn)備工作
首先問自己幾個問題:
- 為什么要跨進(jìn)程通信(IPC)碟联? (進(jìn)程之間是不可以通信的嗎)
- 怎么做到跨進(jìn)程通信? (怎樣用常規(guī)的方式在兩個進(jìn)程之間進(jìn)行通信呢)
- 為什么是 Binder 柿冲? (為什么常規(guī)的跨進(jìn)程方式不行谭期,而要專門使用 Binder)
回答這幾個問題撵割,我們得先了解一下幾個概念结胀。為后面做鋪墊朵栖。
Android 系統(tǒng)是基于 Linux 內(nèi)核的丽猬,因此有必要了解一些相關(guān)知識。
0.1 進(jìn)程隔離
進(jìn)程隔離是為保護(hù)操作系統(tǒng)中進(jìn)程互不干擾而設(shè)計的一組不同硬件和軟件的技術(shù)鸳劳。這個技術(shù)是為了避免 進(jìn)程A 寫入 進(jìn)程B 的情況發(fā)生狰贯。 進(jìn)程的隔離實現(xiàn)也搓,使用了虛擬地址空間赏廓。進(jìn)程A 的虛擬地址和 進(jìn)程B 的虛擬地址不同涵紊,這樣就防止 進(jìn)程A 將數(shù)據(jù)信息寫入 進(jìn)程B。
以上來自維基百科:進(jìn)程隔離的安全性通過禁止進(jìn)程間內(nèi)存的訪問可以方便實現(xiàn)幔摸。相比之下摸柄,一些不安全的操作系統(tǒng)(例如DOS)能夠允許任何進(jìn)程對其他進(jìn)程的內(nèi)存進(jìn)行寫操作。
根據(jù)以上描述既忆,我們可以知道 操作系統(tǒng)的不同進(jìn)程之間驱负,數(shù)據(jù)是不共享的,即禁止進(jìn)程間內(nèi)存的訪問患雇。因此我們可以回答第一個問題跃脊。
Q:為什么要跨進(jìn)程通信
A:根據(jù)上述可以得知,進(jìn)程之間是不可以進(jìn)行通信的苛吱,所以我們需要有某種方式來完成 跨進(jìn)程通信酪术。
0.2 用戶空間 / 內(nèi)核空間
詳細(xì)解釋可參考 Kernel Space Definition
Linux 系統(tǒng)內(nèi)存可以分為兩個不同的區(qū)域:內(nèi)核空間和用戶空間。
內(nèi)核空間是內(nèi)核(即操作系統(tǒng)的核心)執(zhí)行(即運行)并提供其服務(wù)的地方翠储。
用戶空間是指 用戶進(jìn)程(即內(nèi)核以外的所有內(nèi)容)運行的內(nèi)存位置集绘雁。
Linux Kernel 是操作系統(tǒng)的核心,獨立于普通的應(yīng)用程序援所,可以訪問受保護(hù)的內(nèi)存空間庐舟,也有訪問底層硬件設(shè)備的所有權(quán)限。 內(nèi)核的一個角色是管理這個空間中的各個用戶進(jìn)程住拭,并防止它們相互干擾挪略。
對于Kernel這么一個高安全級別的東西,顯然是不容許其它的應(yīng)用程序隨便調(diào)用或訪問的滔岳,所以需要對Kernel提供一定的保護(hù)機(jī)制瘟檩,這個保護(hù)機(jī)制用來告訴那些應(yīng)用程序,你只可以訪問某些許可的資源澈蟆,不許可的資源是拒絕被訪問的墨辛,于是就把Kernel和上層的應(yīng)用程序抽像的隔離開,分別稱之為Kernel Space和User Space趴俘。
簡單理解就是:
內(nèi)核空間可以執(zhí)行任意命令睹簇,調(diào)用系統(tǒng)的一切資源;
用戶空間只能執(zhí)行簡單的運算,不能直接調(diào)用系統(tǒng)資源寥闪;
那么用戶空間肯定會有想 調(diào)用系統(tǒng)資源 的需求太惠,比如應(yīng)用程序訪問文件的等。
根據(jù) Kernel Space Definition 這篇文字的詳細(xì)說明疲憋,我們可以得知:
Kernel space can be accessed by user processes only through the use of system calls.
只有通過使用系統(tǒng)調(diào)用凿渊,用戶進(jìn)程才能訪問內(nèi)核空間。
0.3 系統(tǒng)調(diào)用 / 內(nèi)核態(tài) / 用戶態(tài)
用戶空間訪問內(nèi)核空間的唯一方式就是 系統(tǒng)調(diào)用;通過這個統(tǒng)一入口接口埃脏,所有的資源訪問都是在內(nèi)核的控制下執(zhí)行搪锣,以免導(dǎo)致用戶程序?qū)ο到y(tǒng)資源的越權(quán)訪問,從而保障了系統(tǒng)的安全和穩(wěn)定彩掐。用戶軟件良莠不齊构舟,要是它們亂搞把系統(tǒng)玩壞了怎么辦?因此對于某些特權(quán)操作必須交給安全可靠的內(nèi)核來執(zhí)行堵幽。
當(dāng)一個任務(wù)(進(jìn)程)執(zhí)行系統(tǒng)調(diào)用而陷入內(nèi)核代碼中執(zhí)行時狗超,我們就稱進(jìn)程處于內(nèi)核運行態(tài)(或簡稱為內(nèi)核態(tài))此時處理器處于特權(quán)級最高的(0級)內(nèi)核代碼中執(zhí)行。當(dāng)進(jìn)程在執(zhí)行用戶自己的代碼時朴下,則稱其處于用戶運行態(tài)(用戶態(tài))努咐。即此時處理器在特權(quán)級最低的(3級)用戶代碼中運行。處理器在特權(quán)等級高的時候才能執(zhí)行那些特權(quán)CPU指令殴胧。
0.4 內(nèi)存映射 之 mmap 方法
https://www.cnblogs.com/huxiao-tee/p/4660352.html#_label0
mmap 是 內(nèi)存映射文件 的一種方法麦撵。即將一個文件或者其它對象映射到進(jìn)程的地址空間。實現(xiàn)文件磁盤地址和進(jìn)程虛擬地址空間中一段虛擬地址的一一對應(yīng)關(guān)系溃肪。
Linux 內(nèi)核使用一個 vm_area_struct 結(jié)構(gòu)體來表示一個獨立的虛擬內(nèi)存區(qū)域免胃。
vm_area_struct 內(nèi)包含一個 vm_ops 指針,其內(nèi)部可引出所有針對這個區(qū)域可以使用的系統(tǒng)調(diào)用函數(shù)惫撰。
mmap 函數(shù)就是要創(chuàng)建一個新的 vm_area_struct 結(jié)構(gòu)體羔沙,并將其與文件的物理磁盤地址相連。
總而言之厨钻,常規(guī)文件操作需要從磁盤到頁緩存(處于內(nèi)核空間)再到用戶主存的兩次數(shù)據(jù)拷貝扼雏。而mmap操控文件,只需要從磁盤到用戶主存的一次數(shù)據(jù)拷貝過程夯膀。
具體的分析可查看如下文章
Gityuan Binder 系列
Binder 學(xué)習(xí)指南
Android 接口定義語言 (AIDL)
老羅的 Android 之旅
Android Bander設(shè)計與實現(xiàn) - 設(shè)計篇
相見恨晚 Binder 機(jī)制