Android中關(guān)于Binder常見面試問題小結(jié)
1.簡單介紹下binder
binder是一種進(jìn)程間通訊的機(jī)制
進(jìn)程間通訊需要了解用戶空間和內(nèi)核空間
每個進(jìn)程擁有自己的獨(dú)立虛擬機(jī),系統(tǒng)為他們分配的地址空間都是互相隔離的。 如兩個進(jìn)程需要進(jìn)行通訊,則需要使用到內(nèi)核空間做載體,內(nèi)核空間是所有進(jìn)程共享的一塊內(nèi)存區(qū)域。 而用戶空間切到內(nèi)核空間需要使用到系統(tǒng)api ioctl進(jìn)行通訊。內(nèi)核獲取用戶的數(shù)據(jù)需要使用copy_from_user,內(nèi)核將數(shù)據(jù)發(fā)送給其他進(jìn)程需要使用copy_to_user,這兩個方法是有性能開銷的,對于socket就是使用的這種模式,為了減少這部分的開銷,內(nèi)核提供了binder,binder只需要一次拷貝就可以實現(xiàn)進(jìn)程通訊.
主要是使用mmap的原理:
在內(nèi)核空間和用戶空間都開辟一塊虛擬內(nèi)存區(qū)域同時指向一塊物理地址,這樣內(nèi)核需要傳遞數(shù)據(jù)給用戶空間時,只需要將數(shù)據(jù)拷貝到對應(yīng)的虛擬內(nèi)存地址中,用戶可以通過虛擬內(nèi)存映射關(guān)系,獲取到內(nèi)核中的數(shù)據(jù),實現(xiàn)了一次拷貝通訊。
binder架構(gòu)上面使用的是C/S架構(gòu):

binder中有三要素: 客戶端,服務(wù)端和ServiceManager
binder整體過程:
1.注冊服務(wù) 2.獲取服務(wù) 3.使用服務(wù)

2.Binder的定向制導(dǎo),如何找到目標(biāo)Binder,喚起進(jìn)程或者線程?
數(shù)據(jù)結(jié)構(gòu)流程:
1.server注冊過程
1.server傳入一個flat_binder_object給內(nèi)核態(tài)。內(nèi)核根據(jù)這個flat_binder_object創(chuàng)建binder_node節(jié)點(diǎn),為每個進(jìn)程服務(wù),內(nèi)部有個binder_proc.proc = server進(jìn)程
2.serviceManager在內(nèi)核態(tài)創(chuàng)建binder_ref引用這個binder_node,內(nèi)部有一項desc = 1,2,3..,在用戶態(tài)會創(chuàng)建一個服務(wù)鏈表{name ="server name",handle = "server handle"}
2.client獲取服務(wù)過程
3.client向sm查詢服務(wù),傳遞name
4.sm返回handle給驅(qū)動程序
5.驅(qū)動程序在sm的binder_ref_desc紅黑樹中根據(jù)handle找到binder_ref,再根據(jù)binder_ref.node找到binder_node,最后給client創(chuàng)建新的binder_ref指向這個binder_node,他的desc從1開始binder_ref{desc=1,node = binder_node},驅(qū)動返回desc給client,即handle總結(jié):sm中的handle順序是根據(jù)服務(wù)注冊順序顯示,返回給client中的handle是根據(jù)服務(wù)獲取的順序顯示的
3.client使用handle過程
6.:驅(qū)動里面根據(jù)handle找到找到binder_ref,根據(jù)binder_ref找到binder_node,根據(jù)binder_node找到進(jìn)程server注:
flat_binder_object{
type:是binder實體還是引用,只有需要注冊的服務(wù)可以傳binder實體,其他只能傳handle引用
flag(聯(lián)合體)
binder(實體:處理函數(shù))/handle(引用:服務(wù)的引用):
cookie
}數(shù)據(jù)傳輸過程(進(jìn)程切換):

數(shù)據(jù)如何復(fù)制:

3.Binder中的紅黑樹,為什么會有兩棵binder_ref紅黑樹
refs_by_desc主要是通過desc來查找對應(yīng)的binder_refrefs_by_node主要是通過node來查找對應(yīng)的binder_ref
查找方式不一樣
4.Binder一次拷貝原理
傳統(tǒng)的數(shù)據(jù)拷貝方式如socket:
用戶空間---->內(nèi)核空間:`copy_from_user ` 內(nèi)核空間---->用戶空間:`copy_to_user`
而binder使用mmap機(jī)制
在內(nèi)核空間和用戶空間中間使用物理地址開辟了一個映射關(guān)系 內(nèi)核空間調(diào)用copy_from_user會直接將數(shù)據(jù)拷貝到內(nèi)核空間并反饋到映射后的物理地址上, 由于用戶空間和物理地址也有個映射關(guān)系,用戶空間可以直接通過映射的虛擬地址指針訪問到寫入物理地址的數(shù)據(jù)。 這就是binder一次拷貝的原理
5.Binder傳輸數(shù)據(jù)的大小限制?
對于內(nèi)核可以傳輸?shù)氖?code>4M,但是應(yīng)用層限制在1M-8K范圍內(nèi),這就是在進(jìn)程間傳輸過大的數(shù)據(jù)會導(dǎo)致崩潰的原因
6.系統(tǒng)服務(wù)與bindService等啟動的服務(wù)的區(qū)別
系統(tǒng)服務(wù)需要將服務(wù)注冊到ServiceManager,使用的時候需要通過服務(wù)名稱去ServiceManger中獲取服務(wù)的引用,
而bindService等啟動的服務(wù)是將服務(wù)注冊到AMS中的ServiceMap中,所有的服務(wù)的生命周期都由AMS控制。啟動服務(wù)的進(jìn)程如果需要使用IPC通訊,都是和獲取AMS的代理類進(jìn)行通訊,AMS也是在SystemServer啟動的時候一個注冊到ServiceManager的系統(tǒng)服務(wù)。
7.Binder多線程
binder線程池默認(rèn)提供了15個線程進(jìn)行處理進(jìn)程間并發(fā)事件,如果服務(wù)端線程不夠用,則驅(qū)動會發(fā)出一個信號,應(yīng)用層收到這個信號調(diào)用Register_Thread,這樣驅(qū)動層就可以使用這個新建出來的子線程進(jìn)行數(shù)據(jù)的處理
8.Android APP進(jìn)程天生支持Binder通信的原理是什么?
Android APP進(jìn)程都是由Zygote進(jìn)程孵化出來的。
常見場景:
點(diǎn)擊桌面icon啟動APP,或者startActivity啟動一個新進(jìn)程里面的Activity,最終都會由AMS去調(diào)用Process.start()方法去向Zygote進(jìn)程發(fā)送請求,讓Zygote去fork一個新進(jìn)程,Zygote收到請求后會調(diào)用Zygote.forkAndSpecialize()來fork出新進(jìn)程,之后會通過RuntimeInit.nativeZygoteInit來初始化Andriod APP運(yùn)行需要的一些環(huán)境,而binder線程就是在這個時候新建啟動的
virtual void onZygoteInit()
{
sp proc = ProcessState::self();
//啟動新binder線程loop
proc->startThreadPool();
}9.同一個線程的請求必定是順序執(zhí)行,即使是異步請求(oneway)
一般而言,Client同步阻塞請求Service,直到Service提供完服務(wù)后才返回,不過,也有特殊的,比如請求用ONE_WAY方式,這種場景一般主要是用來通知,至于通知被誰消費(fèi),是否被消費(fèi)壓根不會關(guān)心。 拿ContentService服務(wù)為例子,它是一個全局的通知中心,負(fù)責(zé)轉(zhuǎn)發(fā)通知,而且,一般是群發(fā),由于在轉(zhuǎn)發(fā)的時候,ContentService被看做Client,如果這個時候采用普通的同步阻塞勢必會造成通知的延時發(fā)送送,所以這里的Client采用了oneway,異步。
到此這篇關(guān)于Android中關(guān)于Binder常見面試問題小結(jié)的文章就介紹到這了,更多相關(guān)Android Binder面試內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android調(diào)用手機(jī)攝像頭拍照和錄音功能
這篇文章主要為大家詳細(xì)介紹了Android調(diào)用手機(jī)攝像頭拍照和錄音功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03
在AndroidManifest.xml中uses-sdk內(nèi)屬性意思
本文為大家講解下minSdkVersion、targetSdkVersion、maxSdkVersion、target API level四個數(shù)值的意思與區(qū)別,感興趣的朋友可以參考下哈2013-06-06
Android Studio Kotlin代碼和java代碼相互轉(zhuǎn)化實例
這篇文章主要介紹了Android Studio Kotlin代碼和java代碼相互轉(zhuǎn)化實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Android自定義TextView實現(xiàn)drawableLeft內(nèi)容居中
這篇文章主要介紹了Android自定義TextView實現(xiàn)drawableLeft內(nèi)容居中的相關(guān)資料,需要的朋友可以參考下2017-06-06
android動態(tài)設(shè)置app當(dāng)前運(yùn)行語言的方法
下面小編就為大家?guī)硪黄猘ndroid動態(tài)設(shè)置app當(dāng)前運(yùn)行語言的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03
android實現(xiàn)搜索功能并將搜索結(jié)果保存到SQLite中(實例代碼)
這篇文章主要介紹了android實現(xiàn)搜索功能并將搜索結(jié)果保存到SQLite中,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04

