說說你對 binder 驅動的瞭解?

面試官提了一個問題:說說你對 binder 驅動的瞭解。這個問題雖有些 "面試造火箭" 的無奈,可難點就是亮點、價值所在,是篩選面試者的有效手段。若是讓你回答,你能說出多少呢?咱們來看看 😎、😨 和 🤔️ 三位同窗的回答如何吧node


😎 自認爲無所不知,水平已達應用開發天花板,目前月薪 10k面試

面試官️:說說你對 binder 驅動的瞭解網絡

😎:binder 驅動是很底層的東西,在系統內核中,是 binder 機制的基石。數據結構

面試官:沒了嗎?把你瞭解的都說一下函數

😎:直接讓我說了解很差回答啊,仍是問我問題吧佈局

面試官:好,你剛纔提到了系統內核,那介紹一下用戶空間和內核空間吧學習

😎:不知道,這東西瞭解了也沒什麼用啊!我對業務開發 API 比較瞭解,好比 RecycleView 佈局,我寫的賊溜~線程

面試官:好的,回去等通知吧cdn


😨 業餘時間常常打遊戲、追劇、熬夜,目前月薪 15kserver

面試官:說說你對 binder 驅動的瞭解

😨:binder 機制分爲四部分,binder 驅動、Service Manager、客戶端、服務端。類比網絡通訊,Service Manager 是 DNS,binder 驅動就是路由器,它運行在內核空間,不一樣進程間經過 binder 驅動才能通訊。

面試官:爲何 binder 驅動要運行在內核空間?能夠移到用戶空間嗎?

😨:不行,兩個進程的進程空間有不一樣的虛擬地址映射規則,內存是不共享的,沒法直接通訊。Linux 把進程空間劃分爲用戶空間和內核空間,分別運行用戶程序和系統內核。

用戶空間和內核空間雖也是隔離的,但能夠經過 copy_from_user 將數據從用戶空間拷貝到內核空間,經過 copy_to_user 將數據從內核空間拷貝到用戶空間。

因此 binder 驅動要處於內核空間,才能實現兩個進程間的通訊。通常的 IPC 方式須要分別調用這兩個函數,數據就拷貝了兩次,而 binder 將內核空間與目標用戶空間進行了 mmap,只需調 copy_from_user 拷貝一次便可。

面試官:從用戶空間如何調用內核空間的 binder 驅動呢?

😨:這個不瞭解了,我沒看過 binder 源碼,只是知道大概的通訊方式

面試官:那你對 binder 驅動還有哪些瞭解,都說說吧

😨:嗯... 沒有了

面試官:好的,回去等通知吧


🤔️ 堅持天天學習、不斷的提高本身,目前月薪 30k

面試官:說說你對 binder 驅動的瞭解

🤔️:簡單畫張圖吧:

對 Binder 機制來講,它是 IPC 通訊的路由器,負責實現不一樣進程間的數據交互,是 Binder 機制的核心;對 Linux 系統來講,它是一個字符驅動設備,運行在內核空間,向上層提供 /dev/binder 設備節點及 open、mmap、ioctl 等系統調用。

面試官:你提到了驅動設備,那先說說 Linux 的驅動設備吧

🤔️:Linux 把全部的硬件訪問都抽象爲對文件的讀寫、設置,這一"抽象"的具體實現就是驅動程序。驅動程序充當硬件和軟件之間的樞紐,提供了一套標準化的調用,並將這些調用映射爲實際硬件設備相關的操做,對應用程序來講隱藏了設備工做的細節。

Linux 驅動設備分爲三類,分別是字符設備、塊設備和網絡設備。字符設備就是可以像字節流文件同樣被訪問的設備。對字符設備進行讀/寫操做時,實際硬件的 I/O 操做通常也緊接着發生。字符設備驅動程序一般都會實現 open、close、read 和 write 系統調用,好比顯示屏、鍵盤、串口、LCD、LED 等。

塊設備指經過傳輸數據塊(通常爲 512 或 1k)來訪問的設備,好比硬盤、SD卡、U盤、光盤等。網絡設備是可以和其餘主機交換數據的設備,好比網卡、藍牙等設備。

字符設備中有一個比較特殊的 misc 雜項設備,設備號爲 10,能夠自動生成設備節點。Android 的 Ashmem、Binder 都屬於 misc 雜項設備。

面試官:看過 binder 驅動的 open、mmap、ioctl 方法的具體實現嗎?

🤔️:它們分別對應於驅動源碼 binder.c 中的 binder_open()、binder_mmap()、binder_ioctl() 方法,binder_open() 中主要是建立及初始化 binder_proc ,binder_proc 是用來存放 binder 相關數據的結構體,每一個進程獨有一份。

binder_mmap() 的主要工做是創建應用進程虛擬內存在內核中的一塊映射,這樣應用程序和內核就擁有了共享的內存空間,爲後面的一次拷貝作準備。

binder 驅動並不提供常規的 read()、write() 等文件操做,所有經過 binder_ioctl() 實現,因此 binder_ioctl() 是 binder 驅動中工做量最大的一個,它承擔了 binder 驅動的大部分業務。

面試官:僅 binder_ioctl() 一個方法是怎麼實現大部分業務的?

🤔️:binder 機制將業務細分爲不一樣的命令,調用 binder_ioctl() 時傳入具體的命令來區分業務,好比有讀寫數據的 BINDER_WRITE_READ 命令、 Service Manager 專用的註冊爲 DNS 的命令等等。

BINDER_WRITE_READ 命令最爲關鍵,其細分了一些子命令,好比 BC_TRANSACTION、BC_REPLY 等。BC_TRANSACTION 就是上層最經常使用的 IPC 調用命令了,AIDL 接口的 transact 方法就是這個命令。

面試官:binder 驅動中要實現這些業務功能,必然要用一些數據結構來存放相關數據,好比你上面說 binder_open() 方法時提到的 binder_proc,你還知道其餘的結構體嗎?

🤔️:知道一些,好比:

結構體 說明
binder_proc 描述使用 binder 的進程,當調用 binder_open 函數時會建立
binder_thread 描述使用 binder 的線程,當調用 binder_ioctl 函數時會建立
binder_node 描述 binder 實體節點,對應於一個 serve,即用戶態的 BpBinder 對象
binder_ref 描述對 binder 實體節點的引用,關聯到一個 binder_node
binder_buffer 描述 binder 通訊過程當中存儲數據的Buffer
binder_work 描述一個 binder 任務
binder_transaction 描述一次 binder 任務相關的數據信息
binder_ref_death 描述 binder_node 即 binder server 的死亡信息

其中主要結構體引用關係以下:

面試官:能夠,咱們再來聊聊別的。

這個問題雖有些 "面試造火箭" 的無奈,可難點就是亮點、價值所在,是篩選面試者的有效手段。若是問你這個問題,你能回答多少呢?

如上圖,這裏有一份按模塊分好的 Binder 源碼,並有關鍵步驟註釋。關注公衆號 Android 面試官 留言:binder,便可獲此 Binder 學習必備源碼~

相關文章
相關標籤/搜索