七、Binder 機制初探
Read The Fucking Source Code
0. 準備工作
首先問自己幾個問題:
- 為什麼要跨程序通訊(IPC)? (程序之間是不可以通訊的嗎)
- 怎麼做到跨程序通訊?(怎樣用常規的方式在兩個程序之間進行通訊呢)
- 為什麼是 Binder ?(為什麼常規的跨程序方式不行,而要專門使用 Binder)
回答這幾個問題,我們得先了解一下幾個概念。為後面做鋪墊。
Android 系統是基於 Linux 核心的,因此有必要了解一些相關知識。
0.1 程序隔離
程序隔離是為保護作業系統中程序互不干擾而設計的一組不同硬體和軟體的技術。這個技術是為了避免 程序A 寫入 程序B 的情況發生。 程序的隔離實現,使用了虛擬地址空間。程序A 的虛擬地址和 程序B 的虛擬地址不同,這樣就防止 程序A 將資料資訊寫入 程序B。
以上來自維基百科:程序隔離的安全性通過禁止程序間記憶體的訪問可以方便實現。相比之下,一些不安全的作業系統(例如DOS)能夠允許任何程序對其他程序的記憶體進行寫操作。
根據以上描述,我們可以知道 作業系統的不同程序之間,資料是不共享的,即禁止程序間記憶體的訪問。因此我們可以回答第一個問題。
Q:為什麼要跨程序通訊
A:根據上述可以得知,程序之間是不可以進行通訊的,所以我們需要有某種方式來完成 跨程序通訊。
0.2 使用者空間 / 核心空間
詳細解釋可參考ofollow,noindex">Kernel Space Definition
Linux 系統記憶體可以分為兩個不同的區域:核心空間 和使用者空間 。
核心空間是核心(即作業系統的核心)執行(即執行)並提供其服務的地方。
使用者空間是指 使用者程序(即核心以外的所有內容)執行的記憶體位置集。
Linux Kernel 是作業系統的核心,獨立於普通的應用程式,可以訪問受保護的記憶體空間,也有訪問底層硬體裝置的所有許可權。 核心的一個角色是管理這個空間中的各個使用者程序,並防止它們相互干擾。
對於Kernel這麼一個高安全級別的東西,顯然是不容許其它的應用程式隨便呼叫或訪問的,所以需要對Kernel提供一定的保護機制,這個保護機制用來告訴那些應用程式,你只可以訪問某些許可的資源,不許可的資源是拒絕被訪問的,於是就把Kernel和上層的應用程式抽像的隔離開,分別稱之為Kernel Space和User Space。
簡單理解就是:
核心空間可以執行任意命令,呼叫系統的一切資源;
使用者空間只能執行簡單的運算,不能直接呼叫系統資源;
那麼使用者空間肯定會有想 呼叫系統資源 的需求,比如應用程式訪問檔案的等。
根據Kernel Space Definition 這篇文字的詳細說明,我們可以得知:
Kernel space can be accessed by user processes only through the use of system calls.
只有通過使用系統呼叫 ,使用者程序才能訪問核心空間。
0.3 系統呼叫 / 核心態 / 使用者態
使用者空間訪問核心空間的唯一方式就是系統呼叫 ;通過這個統一入口介面,所有的資源訪問都是在核心的控制下執行,以免導致使用者程式對系統資源的越權訪問,從而保障了系統的安全和穩定。使用者軟體良莠不齊,要是它們亂搞把系統玩壞了怎麼辦?因此對於某些特權操作必須交給安全可靠的核心來執行。
當一個任務(程序)執行系統呼叫而陷入核心程式碼中執行時,我們就稱程序處於核心執行態(或簡稱為核心態 )此時處理器處於特權級最高的(0級)核心程式碼中執行。當程序在執行使用者自己的程式碼時,則稱其處於使用者執行態(使用者態) 。即此時處理器在特權級最低的(3級)使用者程式碼中執行。處理器在特權等級高的時候才能執行那些特權CPU指令。
0.4 記憶體對映 之 mmap 方法
https://www.cnblogs.com/huxiao-tee/p/4660352.html#_label0
mmap 是 記憶體對映檔案 的一種方法。即將一個檔案或者其它物件對映到程序的地址空間。實現檔案磁碟地址和程序虛擬地址空間中一段虛擬地址的一一對應關係。
Linux 核心使用一個 vm_area_struct 結構體來表示一個獨立的虛擬記憶體區域。
vm_area_struct 內包含一個 vm_ops 指標,其內部可引出所有針對這個區域可以使用的系統呼叫函式。
mmap 函式就是要建立一個新的 vm_area_struct 結構體,並將其與檔案的物理磁碟地址相連。
總而言之,常規檔案操作需要從磁碟到頁快取(處於核心空間)再到使用者主存的兩次資料拷貝。而mmap操控檔案,只需要從磁碟到使用者主存的一次資料拷貝過程。