當前位置:首頁 » 安卓系統 » android跨進程

android跨進程

發布時間: 2023-09-25 16:00:57

⑴ Android跨進程傳遞大數據

最近要從 Service 端給 Client 端傳遞圖片數據,之前的數據都是通過 aidl 傳遞:
創建 Parcelable 文件
ImageData.java

test.aidl

運行報錯:

這里導致 DeadObjectException 的原因主要是 binder 創建的 buffer 被占滿了:

傳輸中如果數據大於 free_buffers ,則會拋出 DeadObjectException

socke 傳輸不受大小限制,但實現比較復雜

通過文件傳輸比較簡單,但效率差,而且高版本會受到Android系統許可權限制

將較大數據切割成較小的數據傳輸,此方法是兼顧效率,復雜度較好的方案

定義數據體:

切割數據方法:

將ImageData按順序構建發送:

client接收:

binder 本身也是利用 mmap ,可以利用實現 mmap 的框架,比如 MMKV

如果傳輸的數據是 Bitmap ,還可以用 Bundle 的 putBinder 方案
定義 binder :

發送

接收:

⑵ Android 跨進程通信--Binder篇

話說Binder 其實是由George Hoffman 老哥,在1991年Be公司啟動了一個「openBinder」的項目,該項目的宗旨是研究一個高效的信號傳遞工具,允許多個軟體相互合作,構成一個軟體系統。在BE被parmSource收購以後,openBinder由hackborn繼續開發。在Hackborn加入google之後,他繼續開發出了Android Binder。

而Android系統是基於Linux內核實現的,Linux已經提供了多種進程間通信機制,比如:管道、消息隊列、共享內存和套接字(Socket)等等。

講它們優缺點前先補充說明:
「進程隔離」--這個技術是為了避免進程A寫入進程B的情況發生。 進程的隔離實現,使用了虛擬地址空間進程A的虛擬地址和進程B的虛擬地址不同,這樣就防止進程A將數據信息寫入進程B。進程隔離的安全性通過禁止進程間內存的訪問可以方便實現。相比之下,一些不安全的操作系統DOS能夠允許任何進程對其他進程的內存進行寫操作。

「虛擬內存」-- 是計算機系統內存管理的一種技術。它使得應用程序認為它擁有連續可用的內存(一個連續完整的地址空間),而實際上,它通常是被分隔成多個物理內存碎片,還有部分暫時存儲在外部磁碟存儲器上,在需要時進行數據交換。與沒有使用虛擬內存技術的系統相比,使用這種技術的系統使得大型程序的編寫變得更容易,對真正的物理內存的使用也更有效率。

注意: 虛擬內存 不只是「用磁碟空間來擴展物理內存」的意思——這只是擴充內存級別以使其包含硬碟驅動器而已。把內存擴展到磁碟只是使用虛擬內存技術的一個結果,它的作用也可以通過覆蓋或者把處於不活動狀態的程序以及它們的數據全部交換到磁碟上等方式來實現。對虛擬內存的定義是基於對地址空間的重定義的,即把地址空間定義為「連續的虛擬內存地址」,以藉此「欺騙」程序,使它們以為自己正在使用一大塊的「連續」地址。

⑶ 安卓IPC跨進程通訊:AIDL+Retrofit——AndLinker的初步使用

需要用到安卓跨進程通訊,明指IPC (進程間通信) 的時候,AndLinker是一款Android上的IPC (進程間通信) 庫,結合了 AIDL 和 Retrofit 的諸多特性,且可以與 RxJava 和 RxJava2 的Call Adapters無縫結合使用。

個人簡單理解就是:簡化AIDL流程的一個第三方庫。使用時斗昌需要先了解一下AIDL、retrofit。

以普通Java介面代替AIDL介面

像 Retrofit 一樣生成遠程服務介面的IPC實現

支持的Call Adapters:Call, RxJava  Observable, RxJava2  Observable & Flowable

支持遠程服務回調機制

支持AIDL的所有數據類型

支持AIDL的所有數據定向tag:in,out,inout

支持AIDL的oneway關鍵字

在服務端以及客戶端的項目根目錄的build.gradle中添加jcenter()倉庫

在App的build.gradle中添加如下依賴

AndLinker支持AIDL所有數據類型:

Java語言中的所有原始類型 (如:int,long,char,boolean,等等)

String

CharSequence

Parcelable

List (List中的所有元素必須是此列表中支持的數據類型)

Map (Map中的所有元素必須是此列表中支持的數據類型)

介面里的方法就是按需激銷配求需創建。這里只舉幾個簡單的示例。

⑷ Android跨進程通信-共享內存

還是先看共享內存的使用方法,我主要介紹兩個函數:

通過 shmget() 函數申請共享內存,它的入參如下

通過 shmat() 函數將我們申請到的共享內存映射到自己的用戶空間,映射成功會返回地址,有了這個地址,我們就可以隨意的讀寫數據了,我們繼續看一下這個函數的入參

共享內存的原理是在內存中單獨開辟的一段內存空間,這段內存空間其實就是一個tempfs(臨時虛擬文件),tempfs是VFS的一種文件系統,掛載在/dev/shm上,前面提到的管道pipefs也是VFS的一種文件系統。

由於共享的內存空間對使用和接收進程來講,完全無感知,就像是在自己的內存上讀寫數據一樣,所以也是 效率最高 的一種IPC方式。

上面提到的IPC的方式都是 在內核空間中開辟內存來存儲數據 ,寫數據時,需要將數據從用戶空間拷貝到內核空間,讀數據時,需要從內核空間拷貝到自己的用戶空間,
共享內存就只需要一次拷貝 ,而且共享內存不是在內核開辟空間,所以可以 傳輸的數據量大

但是 共享內存最大的缺點就是沒有並發的控制,我們一般通過信號量配合共享內存使用,進行同步和並發的控制

共享內存在Android系統中主要的使用場景是 用來傳輸大數據 ,並且 Android並沒有直接使用Linux原生的共享內存方式,而是設計了Ashmem匿名共享內存

之前說到有名管道和匿名管道的區別在於有名管道可以在vfs目錄樹中查看到這個管道的文件,但是匿名管道不行, 所以匿名共享內存同樣也是無法在vfs目錄中查看到 的, Android之所以要設計匿名共享內存 ,我覺得主要是為了安全性的考慮吧。

我們來看看共享內存的一個使用場景,在Android中,如果我們想要將當前的界面顯示出來,需要將當前界面的圖元數據傳遞Surfaceflinger去做圖層混合,圖層混合之後的數據會直接送入幀緩存,送入幀緩存後,顯卡就會直接取出幀緩存里的圖元數據顯示了。

那麼我們如何將應用的Activity的圖元數據傳遞給SurfaceFlinger呢?想要將圖像數據這樣比較大的數據跨進程傳輸,靠binder是不行的,所以這兒便用到匿名共享內存。

從谷歌官方提供的架構圖可以看到,圖元數據是通過BufferQueue傳遞到SurfaceFlinger去的,當我們想要繪制圖像的時候, 需要從BufferQueue中申請一個Buffer,Buffer會調用Gralloc模塊來分配共享內存 當作圖元緩沖區存放我們的圖元數據。

可以看到Android的匿名共享內存是通過 ashmem_create_region() 函數來申請共享內存的,它會在/dev/ashmem下創建一個虛擬文件,Linux原生共享內存是通過shmget()函數,並會在/dev/shm下創建虛擬文件。

匿名共享內存是通過 mmap() 函數將申請到的內存映射到自己的進程空間,而Linux是通過*shmat()函數。

雖然函數不一樣,但是Android的匿名共享內存和Linux的共享內存在本質上是大同小異的。

要使用一塊共享內存

⑸ Android之Binder通信篇

Binder跨進程通信的本質是依賴內核驅動將屬於不同Binder進程的數據,從原始進程復制到目標進程,這樣就完成了跨進程通信了。

Binder通過獨特的內存映射機制,在跨進程通信時,可以做到一次拷貝,兩個空間同時使用!如下圖:

Binder跨進程通信是要傳遞數據的,既然有數據必然要佔用內存空間,Android系統規定每一個進程都有一塊Binder內存區,也就是圖1中的 共享內存 ,系統最多隻能給該區域分配4M的物理內存,由於申請這塊內存是通過系統的mmap函數完成的,所以整個映射機制又被稱為mmap機制
為了把這部分說明白,就再盜圖一張,命名圖2吧!

對於Binder驅動,通過 binder_procs 鏈表記錄所有創建的 binder_proc 結構體,binder 驅動層的每一個 binder_proc 結構體都與用戶空間的一個用於 binder 通信的進程一一對應,且每個進程有且只有一個 ProcessState 對象,這是通過單例模式來保證的。在每個進程中可以有很多個線程,每個線程對應一個 IPCThreadState 對象,IPCThreadState 對象也是單例模式,即一個線程對應一個 IPCThreadState 對象,在 Binder 驅動層也有與之相對應的結構,那就是 Binder_thread 結構體。在 binder_proc 結構體中通過成員變數 rb_root threads,來記錄當前進程內所有的 binder_thread。

Binder 線程池:每個 Server 進程在啟動時創建一個 binder 線程池,並向其中注冊一個 Binder 線程;之後 Server 進程也可以向 binder 線程池注冊新的線程,或者 Binder 驅動在探測到沒有空閑 binder 線程時主動向 Server 進程注冊新的的 binder 線程。對於一個 Server 進程有一個最大 Binder 線程數限制,默認為16個 binder 線程,例如 Android 的 system_server 進程就存在16個線程。對於所有 Client 端進程的 binder 請求都是交由 Server 端進程的 binder 線程來處理的。

熱點內容
java中io流 發布:2025-01-25 09:02:54 瀏覽:877
華為高斯資料庫 發布:2025-01-25 08:55:38 瀏覽:30
php是動態語言 發布:2025-01-25 08:45:44 瀏覽:66
伺服器關閉了電腦網路還能用 發布:2025-01-25 08:22:28 瀏覽:587
熱血航線的登錄密碼在哪裡可以看 發布:2025-01-25 08:22:27 瀏覽:769
5系怎麼選擇配置 發布:2025-01-25 08:22:18 瀏覽:842
pythonscipy 發布:2025-01-25 08:18:52 瀏覽:418
恕瑞瑪伺服器地址 發布:2025-01-25 08:18:51 瀏覽:801
oa源碼php 發布:2025-01-25 08:11:31 瀏覽:734
gpc腳本 發布:2025-01-25 08:10:47 瀏覽:317