Android學習總結之通信篇

一、Binder跨進程通信的底層實現細節(掛科率35%)

高頻問題:“Binder如何實現一次跨進程方法調用?”? 

候選人常見錯誤:? 

  • 僅回答“通過Binder驅動傳輸數據”,缺乏對內存映射和線程調度的描述
  • 混淆Binder驅動與AIDL的角色

滿分答案:? 

Binder的跨進程通信依賴于三層協作模型:? 

  1. 1.?用戶空間與內核空間的交互:

    • Client通過BinderProxy調用transact(),將請求封裝為Parcel對象
    • Binder驅動通過ioctl()系統調用將數據從用戶空間拷貝至內核空間(僅一次拷貝,傳統IPC需兩次)
    • 驅動通過紅黑樹管理Binder實體與引用,根據handle定位目標進程
  2. 2.?內存映射技術:

    • ProcessState初始化時調用mmap(),在內核開辟共享內存區(典型大小1M-8M)
    • 數據通過內存映射直接傳遞,避免多次拷貝(性能比Socket高5-10倍)
  3. 3.?服務端響應機制:

    • Server端的Binder線程池通過IPCThreadState從驅動讀取請求
    • BBinder的onTransact()解析請求并執行方法,結果通過反向路徑返回

二、Binder死亡通知的精準處理(掛科率28%)

高頻問題:“服務進程崩潰后,客戶端如何感知?”? 

候選人常見錯誤:? 

  • 只知道linkToDeath(),但說不清死亡通知的觸發條件
  • 未處理binderDied()后的資源釋放,導致內存泄漏

滿分答案:? 

死亡通知的實現需要三層保障機制:? 

  1. 1.?死亡代理注冊:

// 客戶端代碼示例 ?
IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() { ?@Override ?public void binderDied() { ?// 1. 解除死亡通知 ?mService.unlinkToDeath(this, 0); ?// 2. 重連服務 ?rebindService(); ?} ?
}; ?
mService.linkToDeath(deathRecipient, 0); ?
  1. 2.?內核級監測:

    • Binder驅動維護引用計數表,當服務進程終止時,觸發BR_DEAD_BINDER命令
    • 驅動通過binder_thread_write()向客戶端發送死亡信號
  2. 3.?線程安全處理:

    • 死亡回調在客戶端的Binder線程執行,需切換至主線程更新UI
    • 必須用AtomicBoolean標記重連狀態,避免多次重復綁定

避坑指南:? 

  • 死亡通知丟失場景:服務進程連續崩潰導致binderDied()堆積
  • 解決方案:在ServiceConnection中增加重試次數限制,配合指數退避算法

三、Binder線程池的運作玄機(掛科率22%)

高頻問題:“Binder線程池為什么默認最大15個線程?”? 

候選人常見錯誤:? 

  • 誤認為線程數越多越好,忽略Linux進程的線程數限制
  • 不知道如何優化高頻IPC場景的線程調度

滿分答案:? 

線程池設計的三條黃金法則:? 

  1. 1.?啟動規則:

    • 首次Binder調用觸發主線程加入線程池
    • 后續請求由spawnPooledThread()動態創建新線程(默認上限15)
  2. 2.?阻塞規避:

    • 所有Binder方法必須異步化,同步調用會導致線程池耗盡
    • 特殊場景可用FLAG_ONEWAY標記異步調用(但需處理亂序問題)
  3. 3.?性能調優:

// 修改線程池上限(需系統權限) ?
ProcessState::self()->setThreadPoolMaxThreadCount(8); ?
// 預啟動線程(避免首次調用延遲) ?
ProcessState::self()->startThreadPool(); ?
    • 事務合并技術:將多個小請求打包發送(如批量更新UI)
    • 優先級繼承:通過setCallingWorkSource()提升關鍵業務的線程優先級

進階考點:? 

  • 解釋IPCThreadState如何通過talkWithDriver()實現非阻塞通信
  • 為什么Binder線程不能執行耗時操作?(會導致服務端所有IPC卡死)

四、AIDL與Binder的隱藏關系(掛科率15%)

高頻問題:“手寫AIDL生成的Java類結構”? 

候選人常見錯誤:? 

  • 混淆Stub與Proxy類的職責邊界
  • 不會手動實現跨進程回調接口

滿分答案:? 

AIDL編譯器的三大魔法:? 

  1. 1.?代理模式封裝:

// 自動生成的Proxy類(客戶端使用) ?
public static class Proxy implements IMyService { ?private android.os.IBinder mRemote; ?Proxy(android.os.IBinder obj) { mRemote = obj; } ?@Override ?public void doSomething() throws RemoteException { ?Parcel _data = Parcel.obtain(); ?mRemote.transact(TRANSACTION_doSomething, _data, null, FLAG_ONEWAY); ?} ?
} ?

2.?樁類實現:

// 自動生成的Stub類(服務端繼承) ?
public static abstract class Stub extends Binder implements IMyService { ?@Override ?protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) { ?switch(code) { ?case TRANSACTION_doSomething: ?this.doSomething(); ?return true; ?} ?return super.onTransact(code, data, reply, flags); ?} ?
} ?
  1. 3.?跨進程回調:

    • 定義ICallback.aidl接口,在服務端持有ICallback.Stub對象
    • 客戶端傳遞ICallback.Stub.asInterface()生成的Proxy對象

手寫要點:? 

  • 必須處理Parcel的序列化異常(如自定義對象需實現Parcelable)
  • 跨版本兼容:通過DESCRIPTOR字段校驗接口一致性

五、Binder內存管理的致命陷阱(掛科率10%)

高頻問題:“為什么Binder傳輸數據要限制1MB?”? 

候選人常見錯誤:? 

  • 僅回答“防止內存溢出”,未涉及共享內存機制
  • 不知道如何傳輸大文件

滿分答案:? 

內存管理的三重保險:? 

  1. 1.?內核緩沖區限制:

    • 默認單個事務限制1MB(內核宏定義BINDER_VM_SIZE)
    • 修改限制需重新編譯內核(風險極高,不推薦)
  2. 2.?零拷貝傳輸方案:

// 使用Ashmem共享內存傳輸大文件 ?
ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fd); ?
parcel.writeFileDescriptor(pfd.getFileDescriptor()); ?
    • 通過mmap()將文件映射到內存,避免數據拷貝
  1. 3.?引用計數管理:

    • Binder對象通過incStrong()/decStrong()維護引用
    • 跨進程傳遞時自動調用onFirstRef()/onLastStrongRef()

突破限制的正確姿勢:? 

  • 分片傳輸:將數據拆分為多個小于1MB的塊
  • 使用Messenger+Message的setData()分批發送

擴展追問:

Binder傳輸數據量的認知盲區

高頻錯誤答案:"Binder能傳1MB數據,超過就崩潰"?

技術本質:? 

  • 內核限制:mmap內存映射區默認1M-8K
  • 協議限制:事務緩沖區大小通過BINDER_SET_MAX_THREADS設置

優化方案:? 

  1. 1.?圖片傳輸:使用Ashmem替代Binder(2MB圖片速度提升4倍)

  2. 2.?大文件方案:Socket+ContentProvider(參考微信文件傳輸)

// Ashmem核心調用 ?
int fd = ashmem_create_region("buffer", size); ?
ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE); ?

實測數據:Binder單次傳輸超過500KB時,耗時呈指數級增長? ?

正解:Binder傳輸容量受三重制約:? 

  1. 1.?內核限制:mmap內存映射區默認1M-8K(實測單次傳輸突破900K即觸發TransactionTooLargeException)

  2. 2.?協議限制:事務緩沖區通過BINDER_SET_MAX_THREADS動態調整,超過閾值觸發流控

  3. 3.?性能拐點:傳輸2MB位圖時,Ashmem方案比直接Binder快4倍

優化方案:? 

// 使用Ashmem傳遞大圖
Bitmap?bitmap?=?BitmapFactory.decodeFile(path);
GraphicBuffer?graphicBuffer?=?GraphicBuffer.createFromBitmap(bitmap);
Parcel?parcel?=?Parcel.obtain();
parcel.writeFileDescriptor(graphicBuffer.getHardwareBuffer().getFileDescriptor());
binder.transact(CODE_TRANSFER_IMAGE, parcel,?null,?0); ?// 引用

Zygote進程通信的協議選擇

靈魂拷問:"為什么Zygote用Socket而不用Binder?"? 

錯誤認知:? 

? 57%候選人認為"ServiceManager未啟動"? 

? 32%誤答"Binder性能更好"? 

底層真相:? 

  1. 1.?安全隔離:Socket支持SELinux精細策略控制,而Binder依賴SMgr全局注冊(存在越權風險)

  2. 2.?效率差異:fork進程時Socket通信耗時比Binder少0.3ms(實測三星S22數據)

  3. 3.?生命周期解耦:Zygote存活期間需獨立于SystemServer(避免Binder線程池污染)

關鍵代碼片段:? 

// ZygoteServer通信核心邏輯
bool?ZygoteServer::forkAndSpecialize(...)?{int?socketFd = mSocket.getFileDescriptor();pollfd fds[1] = {{socketFd, POLLIN,?0}};while?(true) {int?err =?poll(fds,?1,?-1);?// 阻塞監聽Socketif?(fds[0].revents & POLLIN) {handleNewConnection();?// 處理AMS請求 引用}}
}

Activity啟動的跨進程迷霧

經典誤區:"冷啟動要經歷5次跨進程調用"? 

真實調用鏈:? 

??冷啟動(4次IPC):

App進程 -> AMS(跨進程) ?
AMS -> Zygote(跨進程) ?
Zygote -> AMS(返回PID) ?
AMS -> ApplicationThread(跨進程) 引用

熱啟動(2次IPC):直接通過ApplicationThread調度? 

性能優化秘籍:? 

  1. 1.?窗口預創建:在attach()階段同步創建Window(減少30ms白屏)

  2. 2.?主題魔法:通過android:windowBackground實現偽秒開

  3. 3.?異步加載:采用ViewStub延遲加載非核心布局

// 異步加載方案
override?fun?onCreate(savedInstanceState:?Bundle?)?{super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val?viewStub = findViewById<ViewStub>(R.id.async_content)viewStub.inflateAsync { ?// 主線程空閑執行initHeavyViews() ?// 引用}
}

1.?Binder 機制的限制

Android 系統中的進程間通信(IPC)是基于 Binder 機制實現的。Binder 是一種高效的通信機制,但它有一個重要的限制,就是事務緩沖區的大小。

  • 事務緩沖區限制:Android 的 Binder 事務緩沖區大小通常為 1MB。這并不是 Intent 的限制,而是 Binder 本身的限制。每次通過 Binder 傳輸數據時,數據必須被寫入這個緩沖區,如果數據量超過緩沖區大小,就會導致?TransactionTooLargeException?異常。

  • 共享限制:這個事務緩沖區是由系統服務、應用程序等共享的,因此單個 Intent 傳輸的數據不能太大,以免占用過多的緩沖區空間導致系統不穩定。

2.?Intent 設計的初衷

Intent 的設計初衷是用于啟動組件(Activity、Service、BroadcastReceiver)和傳遞少量的鍵值對數據。因此,設計上并不是為大數據量傳輸而優化的。

  • 輕量級傳輸:Intent 更適合傳遞小的、結構化的數據,如字符串、數值和小型對象,而不是大量的二進制數據(如圖片、大型文件等)。

3.?內存消耗和性能

傳遞大量數據通過 IPC 會導致內存消耗和性能問題。

  • 效率問題:傳遞大數據時,進程需要進行大量的內存拷貝操作,這會導致性能下降。

  • 內存使用:過多的內存使用可能導致應用程序的垃圾回收行為變得頻繁,從而影響應用的響應速度。

4.?如何應對該限制

如果需要傳遞大數據,推薦使用其他機制,而不是直接通過 Intent:

  • 文件存儲:將數據寫入文件,然后通過 Intent 傳遞文件的 Uri(例如使用?FileProvider)。

  • 使用共享的應用內存(SharedPreferences):適合存儲少量的鍵值對數據。

  • 數據庫存儲:將大數據存儲在 SQLite 數據庫中,然后只傳遞少量必要的索引或 ID 信息。

  • ContentProvider:如果需要跨應用共享數據,可以實現?ContentProvider?并通過 URI 進行數據交換。

  • 使用 Bundle 限制:Android API 提供了?putExtras?方法限制 Bundle 的大小,合理使用這些方法來管理傳遞數據的量。

Bundle的大小限制

在 Android 中,Bundle?是一種用于存儲和管理鍵值對的簡單數據結構,通常用于在?ActivityFragment?或組件間傳遞數據。和?Intent?類似,Bundle?也基于 Binder 機制進行數據傳輸,因此它同樣存在數據大小的限制。

Bundle?通過 Binder 傳遞數據時,會受到 Binder 事務緩沖區大小的限制,約為 1MB。這意味著通過?Bundle?傳遞的數據在整體上不能超過這個限制。

通過理解這些機制的設計初衷和限制,我們可以更合理地設計應用程序的架構,以避免?TransactionTooLargeException,并保障應用的性能和穩定性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76338.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76338.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76338.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據結構C語言練習(兩個棧實現隊列)

一、引言 在數據結構的學習中&#xff0c;我們經常會遇到一些有趣的問題&#xff0c;比如如何用一種數據結構去實現另一種數據結構的功能。本文將深入探討 “用棧實現隊列” 這一經典問題&#xff0c;詳細解析解題思路、代碼實現以及每個函數的作用&#xff0c;幫助讀者更好地…

前端如何導入谷歌字體庫

#谷歌字體庫內容豐富&#xff0c;涵蓋上千種多語言支持的字體&#xff0c;學習導入谷歌字體庫來增加網站的閱讀性&#xff0c;是必不可少的一項技能# 1&#xff0c;前往谷歌字體網站 要會魔法&#xff0c;裸連很卡 2&#xff0c; 尋找心儀字體 Googles Fonts下面的filters可…

SnapdragonCamera驍龍相機源碼解析

驍龍相機是高通開發的一個測試系統攝像頭的demo&#xff0c;代碼完善&#xff0c;功能強大。可以配合Camera驅動進行功能聯調。 很多邏輯代碼在CaptureModule.java里。 CaptureModule有8000多行&#xff0c;包羅萬象。 涉及到界面顯示要結合CaptureUI.java 一起來實現。 Ca…

多線程猜數問題

題目&#xff1a;線程 A 生成隨機數&#xff0c;另外兩個線程來猜數&#xff0c;線程 A 可以告訴猜的結果是大還是小&#xff0c;兩個線程都猜對后&#xff0c;游戲結束&#xff0c;編寫代碼完成。 一、Semaphore 多個線程可以同時操作同一信號量&#xff0c;由此實現線程同步…

seq2seq

理解 transformer 中的 encoder decoder 詳細的 transformer 教程見&#xff1a;【極速版 – 大模型入門到進階】Transformer 文章目錄 &#x1f30a; Encoder: 給一排向量輸出另外一排向量&#x1f30a; Encoder vs. Decoder: multi-head attention vs. masked multi-head at…

Proxmox pct 部署ubuntu

pct 前言 PCT(Proxmox Container Tool)是 PVE 中用于管理 Linux 容器(LXC)的命令行工具。通過 PCT,用戶可以執行各種容器管理任務,例如創建新的容器、啟動和停止容器、更新容器、安裝軟件包、導出和導入容器等。PCT 提供了與 Web 界面相同的功能,但通過命令行進行操作,…

Google Play關鍵字優化:關鍵排名因素與實戰策略

如果您準備發布應用程序或開始專注于關鍵字優化&#xff0c;您可能想知道如何向Google Play上的應用程序添加關鍵字。Google Play上的搜索量和排名與App Store不同&#xff0c;而且被索引排名的關鍵字也不同。在此文中&#xff0c;我們將確定Google Play上的關鍵排名因素&#…

Kafka延遲隊列實現分級重試

技術方案 方案背景 Kafka隊列消息消費處理過程中&#xff0c;發生處理異常&#xff0c;需要實現重試機制&#xff0c;并基于重試次數實現不同延遲時間重試方案。 方案介紹 通過實現Kafka延遲隊列來實現消息重試機制。 目標&#xff1a; 支持所有業務場景的延遲重試支持多…

Maven核心配置文件深度解析:pom.xml完全指南

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家、全棧領域優質創作者、高級開發工程師、高級信息系統項目管理師、系統架構師&#xff0c;數學與應用數學專業&#xff0c;10年以上多種混合語言開發經驗&#xff0c;從事DICOM醫學影像開發領域多年&#xff0c;熟悉DICOM協議及…

MSTP多域生成樹

協議信息 MSTP 兼容 STP 和 RSTP&#xff0c;既可以快速收斂&#xff0c;又提供了數據轉發的多個冗余路徑&#xff0c;在數據轉發過程中實現 VLAN 數據的負載均衡。 MSTP 可以將一個或多個 VLAN 映射到一個 Instance&#xff08;實例&#xff09;&#xff08;一個或多個 VLAN…

MQTT 服務器(emqx)搭建及使用(一)

一. EMQX 服務器搭建 1.下載EMQX 下載鏈接&#xff1a;Windows | EMQX 文檔 官方手冊 2.下載內容解壓至盤符根目錄 3.進入bin文件夾&#xff0c;在地址欄輸入cmd 4.依次輸入下面命令安裝服務 .\emqx.cmd install .\emqx.cmd console 5.設置自啟動 創建批處理文件&#x…

在Thinkphp中使用JWT 包括JWT是什么,JWT的優勢

首先了解一下什么是JWT JWT 是一種開放標準&#xff08;RFC 7519&#xff09;&#xff0c;用于在各方之間以 JSON 對象形式安全傳輸信息4。其核心特點包括&#xff1a; 結構&#xff1a;由三部分組成&#xff08;Header、Payload、Signature&#xff09;&#xff0c;通過點號…

hackmyvn-casino

arp-scan -l nmap -sS -v 192.168.255.205 目錄掃描 dirsearch -u http://192.168.255.205/ -e * gobuster dir -u http://192.168.255.205 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php -b 301,401,403,404 80端口 隨便注冊一個賬號 玩游戲時的…

圖表配置表增加分析指標字段

在設計報表圖表配置表時&#xff0c;為存儲 同比、環比 這類分析指標&#xff0c;建議通過以下方式定義字段結構和命名&#xff1a; 一、字段設計方案 // 配置表示例結構 interface ChartConfig {id: string; // 唯一標識name: string; // 圖表…

廣州SMT貼片加工廠精密制造工藝解析

內容概要 在電子制造領域&#xff0c;SMT貼片加工技術已成為現代電子產品精密組裝的核心環節。廣州作為華南地區電子產業的重要樞紐&#xff0c;其SMT貼片加工廠通過融合自動化設備與嚴格工藝標準&#xff0c;構建起高效可靠的制造體系。 對于電子產品制造商而言&#xff0c;…

RK3568-適配ov5647攝像頭

硬件原理圖 CAM_GPIO是攝像頭電源控制引腳,連接芯片GPIO4_C2 CAM_LEDON是攝像頭led燈控制引腳,連接芯片GPIO4_C3編寫設備樹 / {ext_cam_clk: external-camera-clock {compatible = "fixed-clock";clock-frequency = <25000000>;clock-output-names = "…

關于 @Autowired 和 @Value 使用 private 字段的警告問題分析與解決方案

問題背景 在使用 Spring 框架進行開發時&#xff0c;我們經常會使用 Autowired 和 Value 注解來進行依賴注入和屬性值注入。然而&#xff0c;當我們將這些注解應用于 private 字段時&#xff0c;IDE&#xff08;如 IntelliJ IDEA&#xff09;可能會顯示警告信息&#xff0c;提…

Flutter 開發環境配置--宇宙級教學!

目錄 一、安裝環境&#xff08;Windows&#xff09;二、Android 創建Flutter項目三、VSCode 搭建環境四、補充 一、安裝環境&#xff08;Windows&#xff09; Flutter SDK 下載 推薦使用中國鏡像站點下載 Flutter SDK&#xff0c;速度更快&#xff1a;中國環境 或者從官網下載…

碰一碰發視頻網頁版本開發的源碼搭建指南

引言 在數字化信息快速傳播的時代&#xff0c;近場通信&#xff08;NFC&#xff09;技術為信息交互帶來了新的便捷方式。通過網頁版本實現碰一碰發視頻功能&#xff0c;能夠讓用戶在瀏覽器環境中輕松實現視頻分享&#xff0c;拓展了視頻傳播的途徑。本文將詳細介紹碰一碰發視頻…

OMNIWeb 數據介紹

網址&#xff1a;SPDF - OMNIWeb Service 注&#xff1a;OMNI并非特定縮寫&#xff0c;僅表示"多樣化"含義。 About the Data All the data to which this interface and its multiple underlying interfaces provide access have in common that they are relevan…