Android 面試筆記整理-Binder機制

作者:浪人筆記

面試可能會問到的問題

  1. 從IPC的方式問到Binder的優勢
  2. 為什么zygote跟其他服務進程的通訊不使用Binder
  3. Binder線程池和Binder機制

等等這些問題都是基于你對Binder的理解還有對其他IPC通訊的理解

IPC方式有多少種

  • 傳統的IPC方式有Socket、共享內存、管道、信號量等
  • 安卓特有的是Binder,其他系統也有自己定義的比如window的wfc(Windows Communication Foundation)

Binder機制的優勢

傳統的ipc管道跟信號量都是比較輕的,基本不能用于復雜的IPC通訊,Socket有個缺點就是數據要復制兩遍,第一遍是進程A復制到Socket通道,第二遍是Socket通道復制到進程B。共享內存的缺點就是不方便管理,如果頻繁的對共享內存進行操作很可能會導致死鎖、饑餓等問題。

為了解決這個痛點,安卓設計了Binder的通訊機制,提供更高效、安全、可靠的方式。下圖是Binder機制圖。只需要在內核里面復制一遍,這里可以簡單的理解為單例模式,大家都只需要對Binder內存區域做操作,內存只有一份。

還有一些概念,比如我們應該都聽說Binder是內核里面的,Binder是怎么用到安卓系統里面的,再看一個圖

這里面有四個角色,其實很好理解,兩個進程、一個Binder內核空間、一個ServiceManager服務。兩個進程時采用的C/S結構一個客戶端一個服務端。

  1. Binder內核空間就是一塊存在于內核區的內存理解為一個通道

  2. ServiceManager是安卓的核心服務之一,AMS、PMS、WMS這些是一樣的。它里面提供了很多線程池。Binder線程池只是其中的一種。在這里可以理解為是管理Binder給外部用的提供了一個注冊機制用于識別不同的進程。下面是其他的幾個線程池

    • Activity Manager線程池:用于處理Activity啟動、停止等操作,保證UI界面的流暢性。
    • JobScheduler線程池:用于調度執行后臺任務。
    • MediaServer線程池:用于處理音視頻等媒體數據。
    • SurfaceFlinger線程池:用于處理UI界面繪制等操作。

有沒有想過為什么要搞那么線程池,還要搞那么多個。其實也比較好理解,因為ServiceManager這個類的有很多地方用到,不可能是單線程處理的,這樣就堵塞了。為什么搞那么多線程池是因為不同的功能不同比如有些調用比較頻繁有些需要比較多的cpu。只有一個線程池的話很容易會導致占用時間過長等問題。

  1. server進程需要提供方法被別人調用,需要先在ServiceManager里面注冊。
  2. server注冊完以后會提供接口給client進程調用

來到這里應該可以回答剩下的那兩個問題了。

Binder線程池和Binder機制

  • Binder線程池是ServiceManager提供的,利用的是Binder內核機制。
  • Binder機制是安卓為了提供更高效、穩定、可靠的方式實現的一套基于內核的IPC機制。

為什么zygote進程跟其他進程通訊使用socket而不是binder

  1. Binder雖然在內核,但是提供服務的是ServiceManager,這個時候如果要給AMS提供Binder IPC就需要等ServiceManager先初始化好,這個是沒辦法保證的,如果要保證這個先后順序又要搞多一套進程通訊就更麻煩了。
  2. 另外,由于Zygote進程只與少數幾個進程進行通訊,使用Socket通訊的開銷相對較小,因此選擇Socket通訊更加合適。而且這里面是優化過的LocalSocket效率會更高。

上面一直說內核空間,那內核空間跟用戶空間有什么區別呢?

  1. 內核程序運行在操作系統的內核空間,具有更高的權限和更快的執行速度,能夠實現更底層的操作,如硬件驅動、文件系統等,因此通常用于操作系統的核心功能的實現。

  2. 用戶程序運行在操作系統的用戶空間,具有更多的自由度和可移植性,能夠實現更豐富的功能,如應用程序、服務進程等,因此通常用于操作系統的外圍功能和應用程序的實現。

簡單的說就是內核空間有操作內存的方法,但是這一塊對用戶空間是封閉的,用戶空間里面操作的都是內核提供的服務。比如操作文件用到的文件系統模塊和操作內存用到的內存管理模塊。拿內存管理模塊里面用到的kmallockfree來說。這兩個方法在用戶空間就調用不到,這是內核封裝的方法。

`kmalloc()` 和 `kfree()`: 內核內存分配器,用于在內核空間中動態分配和釋放內存。// 這個還并不是c/c++的原生方法,是內核自己封裝的

再看一下比如使用Binder的時候我們傳的是一個序列化的文件,那他是怎么映射到內存中的?

在內核中有vm_map_ramvm_insert_page這些方法可以把文件插入到內存地址中。而如果在用戶空間需要跟這些打交道用到的還是內存管理模塊的mmap這些。 mmap 的實現在內核中使用了 vm_area_struct。意思是內存管理模塊提供給外面的一層封裝。所以與其這么麻煩還不如直接放到內核里面更合適。

這些方法其實都不重要,只需要知道一點,這些方法在用戶進程空間是拿不到的


基于Binder的IPC

這里是一些基礎,可以不看了。因為這些用的少,方便自己以后看

AIDL

服務端

// IMyService.aidl
interface IMyService {int add(int a, int b);
}// MyService.java
public class MyService extends Service {@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}private class MyBinder extends IMyService.Stub {@Overridepublic int add(int a, int b) throws RemoteException {return a + b;}}
}

客戶端

// MainActivity.java
public class MainActivity extends AppCompatActivity {private IMyService mService;private ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mService = IMyService.Stub.asInterface(service);try {int result = mService.add(1, 2);Toast.makeText(MainActivity.this, "Result: " + result, Toast.LENGTH_SHORT).show();} catch (RemoteException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {mService = null;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this, MyService.class);bindService(intent, mConnection, Context.BIND_AUTO_CREATE);}@Overrideprotected void onDestroy() {super.onDestroy();unbindService(mConnection);}
}

Messager

輕量級的AIDL只能單線程 服務端 MessengerService.java:

public class MessengerService extends Service {private static class IncomingHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 1:String clientMessage = (String) msg.obj;Log.i("MessengerService", "Received message from client: " + clientMessage);// Send a response back to the clientMessenger clientMessenger = msg.replyTo;Message replyMessage = Message.obtain(null, 2);Bundle bundle = new Bundle();bundle.putString("serverResponse", "Hello from server!");replyMessage.setData(bundle);try {clientMessenger.send(replyMessage);} catch (RemoteException e) {Log.e("MessengerService", "Failed to send message to client", e);}break;default:super.handleMessage(msg);}}}private final Messenger mMessenger = new Messenger(new IncomingHandler());@Overridepublic IBinder onBind(Intent intent) {return mMessenger.getBinder();}
}

客戶端 MessengerClient.java:

public class MessengerClient extends AppCompatActivity {private Messenger mMessenger;private static class IncomingHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 2:String serverMessage = msg.getData().getString("serverResponse");Log.i("MessengerClient", "Received message from server: " + serverMessage);break;default:super.handleMessage(msg);}}}private final Messenger mClientMessenger = new Messenger(new IncomingHandler());@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this, MessengerService.class);bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);}@Overrideprotected void onDestroy() {super.onDestroy();unbindService(mServiceConnection);}private final ServiceConnection mServiceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mMessenger = new Messenger(service);sendMessageToServer();}@Overridepublic void onServiceDisconnected(ComponentName name) {mMessenger = null;}};private void sendMessageToServer() {if (mMessenger == null) {return;}Message message = Message.obtain(null, 1);message.obj = "Hello from client!";message.replyTo = mClientMessenger;try {mMessenger.send(message);} catch (RemoteException e) {Log.e("MessengerClient", "Failed to send message to server", e);}}
}

廣播、內容提供者

……

關于Android 面試筆記的真理還有許多知識點在這不能一一的展示,為了方便大家進行復習查閱,這邊我整理成了文檔的形式了,大家可以進行參考一下:https://qr18.cn/CgxrRy

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

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

相關文章

llvm-dyn_cast模板函數

dyn_cast dyn_cast是LLVM中用于執行安全的向下轉型(downcasting)的一個模板函數。在C中,向下轉型是將基類的指針或引用轉換為派生類的指針或引用。這種轉型在運行時進行,如果轉型失敗(即,如果基類的對象實…

云計算虛擬仿真實訓平臺

一、云計算虛擬仿真系統概述 云計算虛擬仿真系統是一種基于云計算技術和虛擬化技術的系統,用于實現各種仿真和模擬任務。它可以提供強大的計算能力和資源管理,為用戶提供靈活、高效、可擴展的仿真環境。 該系統通常由一組服務器、網絡和存儲設備組成&am…

uniapp開發小程序-有分類和列表時,進入頁面默認選中第一個分類

一、效果: 如下圖所示,進入該頁面后,默認選中第一個分類,以及第一個分類下的列表數據。 二、代碼實現: 關鍵代碼: 進入頁面時,默認調用分類的接口,在分類接口里做判斷&#xff…

Linux c語言字節序

文章目錄 一、簡介二、大小端判斷2.1 聯合體2.2 指針2.3 網絡字節序 一、簡介 字節序(Byte Order)指的是在存儲和表示多字節數據類型(如整數和浮點數)時,字節的排列順序。常見的字節序有大端字節序(Big En…

神經網絡基礎-神經網絡補充概念-08-邏輯回歸中的梯度下降算法

概念 邏輯回歸是一種用于分類問題的機器學習算法,而梯度下降是優化算法,用于更新模型參數以最小化損失函數。在邏輯回歸中,我們使用梯度下降算法來找到最優的模型參數,使得邏輯回歸模型能夠更好地擬合訓練數據。 邏輯回歸中的梯…

無監督學習之主成分分析-半導體制造高維數據如何降維

數據降維不只存在于半導體數據中,它是存在于各行各業的,我們要分析的數據維數較多的時候全部輸入維數較大這時就要采取降維的方法綜合出主要的幾列用于我們的分析。 PCA的哲學理念是要抓住問題的主要矛盾進行分析,是將多指標轉化為少數幾個…

前端技術棧es6+promise

let入門使用、 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>let 基本使用</title><script type"text/javascript">let name "hspedu教育";//老韓解讀//1. conso…

蘋果Mac像Windows一樣使用

一、將磁盤訪問設置的像Windows一樣&#xff1a; 1.1、點擊任務欄第一個按鈕打開“訪達”&#xff0c;點擊菜單欄上的訪達-偏好設置&#xff1a; 1.2、勾選“硬盤”&#xff0c;這樣macOS的桌面上就會顯示一個本地磁盤&#xff0c;之后重命名為磁盤根&#xff0c;相當于window…

SPF9139全力適配ios16與鴻蒙3.0,超實用數據提取、分析、恢復能力UP!

? 如今&#xff0c;群聊已成為人們必不可少的溝通窗口 家人群&#xff0c;好友群&#xff0c;班級群 粉絲群&#xff0c;交友群&#xff0c;工作群 …… 各類群聊鋪天蓋地般涌來的同時 也有一些群聊淪為了 賭博、傳播淫穢視頻、發表不當言論 等違法犯罪行為滋生之地 與…

mac 可以進行單片機(stm32)的開發嗎?

當涉及到在Mac上進行單片機開發時&#xff0c;是完全可行的。以下是為什么Mac適合單片機開發的解釋&#xff1a;開發工具&#xff1a;針對STM32單片機&#xff0c;你可以使用多種開發工具。一個常用的選擇是Segger Embedded Studio&#xff0c;它是一個功能強大的集成開發環境&…

ClickHouse(十八):Clickhouse Integration系列表引擎

進入正文前&#xff0c;感謝寶子們訂閱專題、點贊、評論、收藏&#xff01;關注IT貧道&#xff0c;獲取高質量博客內容&#xff01; &#x1f3e1;個人主頁&#xff1a;含各種IT體系技術&#xff0c;IT貧道_Apache Doris,大數據OLAP體系技術棧,Kerberos安全認證-CSDN博客 &…

IDEA常用設置與maven項目部署

目錄 前言 一、Idea是什么 二、Idea的優點 三、Idea的常用設置 主題設置 設置鼠標懸浮提示 忽略大小寫提示 自動導包 取消單行顯示Tabs 設置字體 配置類文檔注釋信息模版 設置文件編碼 設置自動編譯 水平或者垂直顯示代碼 快捷方式改成eclipse 設置默認瀏覽器…

Java并發編程(六)線程池[Executor體系]

概述 在處理大量任務時,重復利用線程可以提高程序執行效率,因此線程池應運而生。 它是一種重用線程的機制,可以有效降低內存資源消耗提高響應速度。當任務到達時&#xff0c;任務可以不需要的等到線程創建就能立即執行線程池可以幫助我們更好地管理線程的生命周期和資源使用,…

Jmeter - 函數助手

目錄 __StringFromFile __CSVRead __counter __RandomString __StringFromFile StringFromFile函數用于獲取文本文件的值&#xff0c;一次讀取一行 1、輸入文件的全路徑&#xff1a;填入文件路徑 2、存儲結果的變量名&#xff08;可選&#xff09; 3、Start file sequence …

Tomcat+Http+Servlet

文章目錄 1.HTTP1.1 請求和響應HTTP請求&#xff1a;請求行請求頭請求體HTTP響應&#xff1a;響應行&#xff08;狀態行&#xff09;響應頭響應體 2. Apache Tomcat2.1 基本使用2.2 IDEA中創建 Maven Web項目2.3 IDEA中使用Tomcat 3. Servlet3.1 Servlet快速入門3.2 Servlet執行…

游戲中的UI適配

引用參考&#xff1a;感謝GPT UI適配原理以及常用方案 游戲UI適配是確保游戲界面在不同設備上以不同的分辨率、屏幕比例和方向下正常顯示的關鍵任務。下面是一些常見的游戲UI適配方案&#xff1a; 1.分辨率無關像素&#xff08;Resolution-Independent Pixels&#xff09;&a…

CentOS 8 安裝 oracle 23c CentOS9 Error deal

1.環境準備 軟件準備 序號 軟件 下載地址 1 VirtualBox https://www.virtualbox.org/wiki/Downloads2 CentOS Stream 8 https://mirrors.tuna.tsinghua.edu.cn/centos/8-stream/isos/x86_64/CentOS-Stream-8-x86_64-latest-dvd1.iso3 oracle-database-free-23c # cd ~/Down…

Vue 3 中定義組件常用方法

在Vue 3 中有多種定義組件的方法。從選項到組合再到類 API&#xff0c;情況大不相同 1、方式一&#xff1a;Options API 這是在 Vue 中聲明組件的最常見方式。從版本 1 開始可用&#xff0c;您很可能已經熟悉它。一切都在對象內聲明&#xff0c;數據在幕后由 Vue 響應。它不是…