### IPC
#### 1、Android中進程和線程的關系? 區別?
> * 參考回答:
> * 線程是CPU調度的**最小單元**,同時線程是一種**有限**的系統資源
> * 進程一般指一個執行單元,在PC和移動設備上一個程序或則一個應用
> * 一般來說,一個App程序**至少有一個**進程,一個進程**至少有一個**線程(包含與被包含的關系), 通俗來講就是,在App這個工廠里面有一個進程,線程就是里面的生產線,但主線程(主生產線)只有一條,而子線程(副生產線)可以有多個
> * 進程有自己獨立的地址空間,而進程中的線程共享此地址空間,都可以**并發**執行
> * 推薦文章:
> * [Android developer官方文檔--進程和線程](https://developer.android.com/guide/components/processes-and-threads?hl=zh-cn)
#### 2、如何開啟多進程 ? 應用是否可以開啟N個進程 ?
> * 參考回答:
> * 在AndroidMenifest中給四大組件指定屬性android:process開啟多進程模式
> * 在內存允許的條件下可以開啟N個進程
> * 推薦講解:
> * [如何開啟多進程?應用是否可以開啟N個進程?](https://github.com/qmsggg/qmsggg_BlogCollect/issues/158)
#### 3、為何需要IPC?多進程通信可能會出現的問題?
> * 參考回答:
> * 所有運行在不同進程的四大組件(Activity、Service、Receiver、ContentProvider)共享數據都會失敗,這是由于Android為每個應用分配了獨立的虛擬機,不同的虛擬機在內存分配上有不同的地址空間,這會導致在不同的虛擬機中訪問同一個類的對象會產生多份副本。比如常用例子(**通過開啟多進程獲取更大內存空間、兩個或則多個應用之間共享數據、微信全家桶**)
> * 一般來說,使用多進程通信會造成如下幾方面的問題
> * **靜態成員和單例模式完全失效**:獨立的虛擬機造成
> * **線程同步機制完全實效**:獨立的虛擬機造成
> * **SharedPreferences的可靠性下降**:這是因為Sp不支持兩個進程并發進行讀寫,有一定幾率導致數據丟失
> * **Application會多次創建**:Android系統在創建新的進程會分配獨立的虛擬機,所以這個過程其實就是啟動一個應用的過程,自然也會創建新的Application
> * 推薦文章:
> * [Android developer官方文檔--進程和線程](https://developer.android.com/guide/components/processes-and-threads?hl=zh-cn)
#### 4、Android中IPC方式、各種方式優缺點,為什么選擇Binder?
> * 參考回答:
> 
>
> 與Linux上傳統的IPC機制,比如System V,Socket相比,Binder好在哪呢?
> * **傳輸效率高、可操作性強**:傳輸效率主要影響因素是內存拷貝的次數,拷貝次數越少,傳輸速率越高。從Android進程架構角度分析:對于消息隊列、Socket和管道來說,數據先從發送方的緩存區拷貝到內核開辟的緩存區中,再從內核緩存區拷貝到接收方的緩存區,一共兩次拷貝,如圖:
> 
>
> 而對于Binder來說,數據從發送方的緩存區拷貝到內核的緩存區,而接收方的緩存區與內核的緩存區是映射到同一塊物理地址的,節省了一次數據拷貝的過程,如圖:
> 
>
> 由于共享內存操作復雜,綜合來看,Binder的傳輸效率是最好的。
> * **實現C/S架構方便**:Linux的眾IPC方式除了Socket以外都不是基于C/S架構,而Socket主要用于網絡間的通信且傳輸效率較低。Binder基于C/S架構 ,Server端與Client端相對獨立,穩定性較好。
> * **安全性高**:傳統Linux IPC的接收方無法獲得對方進程可靠的UID/PID,從而無法鑒別對方身份;而Binder機制為每個進程分配了UID/PID且在Binder通信時會根據UID/PID進行有效性檢測。
> * 推薦文章:
> * [為什么 Android 要采用 Binder 作為 IPC 機制?](https://www.zhihu.com/question/39440766)
#### 5、Binder機制的作用和原理?
> * 參考回答:
> * Linux系統將一個進程分為**用戶空間**和**內核空間**。對于進程之間來說,用戶空間的數據不可共享,內核空間的數據可共享,為了保證安全性和獨立性,一個進程不能直接操作或者訪問另一個進程,即Android的進程是相互獨立、隔離的,這就需要跨進程之間的數據通信方式
>
> 
>
> * 一次完整的 Binder IPC 通信過程通常是這樣:
> * 首先 Binder 驅動在內核空間創建一個數據接收緩存區;
> * 接著在內核空間開辟一塊內核緩存區,建立內核緩存區和內核中數據接收緩存區之間的映射關系,以及內核中數據接收緩存區和接收進程用戶空間地址的映射關系;
> * 發送方進程通過系統調用 copyfromuser() 將數據 copy 到內核中的內核緩存區,由于內核緩存區和接收進程的用戶空間存在內存映射,因此也就相當于把數據發送到了接收進程的用戶空間,這樣便完成了一次進程間的通信。
>
> 
>
#### 6、Binder框架中ServiceManager的作用?
> * 參考回答:
> * **Binder框架** 是基于 C/S 架構的。由一系列的組件組成,包括 Client、Server、ServiceManager、Binder驅動,其中 Client、Server、Service Manager 運行在用戶空間,Binder 驅動運行在內核空間
> 
>
> * **Server&Client**:服務器&客戶端。在Binder驅動和Service Manager提供的基礎設施上,進行Client-Server之間的通信。
> * **ServiceManager**(如同DNS域名服務器)服務的管理者,將Binder名字轉換為Client中對該Binder的引用,使得Client可以通過Binder名字獲得Server中Binder實體的引用。
> * **Binder驅動**(如同路由器):負責進程之間binder通信的建立,傳遞,計數管理以及數據的傳遞交互等底層支持。
> 
>
> 圖片出自Carson\_Ho文章 —— Android跨進程通信:圖文詳解 Binder機制 原理
#### 7、Bundle傳遞對象為什么需要序列化?Serialzable和Parcelable的區別?
> * 參考回答:
> * 因為bundle傳遞數據時只支持基本數據類型,所以在傳遞對象時需要序列化轉換成可存儲或可傳輸的本質狀態(字節流)。序列化后的對象可以在網絡、IPC(比如啟動另一個進程的Activity、Service和Reciver)之間進行傳輸,也可以存儲到本地。
> * 序列化實現的兩種方式:實現Serializable/Parcelable接口。不同點如圖:
> 
>
#### 8、講講AIDL?原理是什么?如何優化多模塊都使用AIDL的情況?
> * 參考回答:
> * AIDL(Android Interface Definition Language,Android接口定義語言):如果在一個進程中要調用另一個進程中對象的方法,可使用AIDL生成可序列化的參數,AIDL會生成一個服務端對象的代理類,通過它客戶端實現間接調用服務端對象的方法。
> * AIDL的本質是系統提供了一套可快速實現Binder的工具。關鍵類和方法:
> * **AIDL接口**:繼承IInterface。
> * **Stub類**:Binder的實現類,服務端通過這個類來提供服務。
> * **Proxy類**:服務器的本地代理,客戶端通過這個類調用服務器的方法。
> * **asInterface()**:客戶端調用,將服務端的返回的Binder對象,轉換成客戶端所需要的AIDL接口類型對象。如果客戶端和服務端位于統一進程,則直接返回Stub對象本身,否則返回系統封裝后的Stub.proxy對象
> * **asBinder()**:根據當前調用情況返回代理Proxy的Binder對象。
> * **onTransact()**:運行服務端的Binder線程池中,當客戶端發起跨進程請求時,遠程請求會通過系統底層封裝后交由此方法來處理。
> * **transact()**:運行在客戶端,當客戶端發起遠程請求的同時將當前線程掛起。之后調用服務端的onTransact()直到遠程請求返回,當前線程才繼續執行。
> * 當有多個業務模塊都需要AIDL來進行IPC,此時需要為每個模塊創建特定的aidl文件,那么相應的Service就會很多。必然會出現系統資源耗費嚴重、應用過度重量級的問題。解決辦法是建立Binder連接池,即將每個業務模塊的Binder請求統一轉發到一個遠程Service中去執行,從而避免重復創建Service。
> * **工作原理**:每個業務模塊創建自己的AIDL接口并實現此接口,然后向服務端提供自己的唯一標識和其對應的Binder對象。服務端只需要一個Service,服務器提供一個queryBinder接口,它會根據業務模塊的特征來返回相應的Binder對象,不同的業務模塊拿到所需的Binder對象后就可進行遠程方法的調用了