面試的時候,面試官問你說,簡單說一下android的binder機制,你會怎麼回答?
我想,我會這麼說。
在android啟動的時候,zygote程序孵化出第乙個子程序叫systemserver,而在這個程序中,很多系統提供的服務,比如activitymanagerserivce, powermanagerservice等,都在此程序中的某一條執行緒上執行。
基於linux的使用者安全機制,它們是沒有辦法直接訪問到上述系統服務的。
而binder機制則是android系統實現程序間通訊(ipc)的機制之一。
面試官可能還會問,那麼binder機制是怎麼實現的呢?
我覺得,要想知道binder機制是怎麼實現的,首先要知道下面四個概念:
1)server
2)client
3)servicemanager
4)binder驅動
server和client無需多說,我們只需要知道乙個是用來提供服務的,乙個是獲取服務的,並且分別執行在不同的程序當中。
那麼servicemanager是用來幹什麼的呢?
在前面一篇文章,關於android的啟動過程中,我們有提到,servicemanager是和zygote程序一樣,是android系統的守護程序之一。
它的主要作用,就是幫助系統去維護眾多的service列表,所以叫service manager。
它就像個**本,你要打**給某個人問點事情(想要獲取某種service),但是你沒有這個人的**(不知道service的訪問點,只知道名字),於是你先找到**本(servicemanager),在**本上找到這個人的**(通過名字找到**),然後你才能打**給他(開始獲取service)。
我們知道,servicemanager,也是乙個單獨的程序。要找到servicemanager,本身也要涉及到程序間通訊啊,不是嗎?
是的。從client和server的角度來看,servicemanager永遠都是乙個server,任何訪問servicemanager的都是client。
我們先想一想,servicemanager本身就是乙個程序,那為什麼這個程序就能夠成為servicemanager呢?
回想一下,在android啟動servicemanager程序的時候,都做了什麼事?
1)首先開啟「/dev/binder」裝置檔案,對映記憶體
2)利用binder_set_context_mgr命令,令自己成為上下文管理者,其實也就是成為servicemanager。
3)進入乙個無限迴圈,等待client的請求到來。
所以,是通過binder驅動,通過命令"binder_set_context_mgr",讓某個程序成為servicemanager的。
面試官這時候,又適當的提了乙個問題,binder驅動是用來幹什麼的?它跟網絡卡驅動,音效卡驅動一樣的嗎?
不一樣。
binder驅動其實跟硬體沒有什麼關係,它就是一段執行在核心空間的**,通過乙個叫"/dev/binder"的檔案在核心空間和使用者空間來回搬資料。
它是整個binder機制的核心。正是通過它,binder才能實現程序間的通訊。
因為server, client和servicemanager是執行在使用者空間,不同的程序,彼此是不能互相訪問的。
那麼在不同的程序間,要進行資料的傳遞,只有通過核心空間來傳遞資料,
而只有binder驅動是工作在核心空間中的。
它負責binder節點的建立,負責binder在程序間的傳遞,負責對binder引用的計數管理,在不同程序間傳輸資料報等底層操作。
整個程序間通訊的大部分工作都是通過 open(), mmap()和 ioctl()等檔案操作,在核心空間與使用者空間中進進出出,來實現的。
面試官接著問,那"binder_set_context_mgr"又是怎麼回事?
是這樣的。
servicemanager程序啟動的時候,此時它還不是servicemanager呢。
不過,當它開啟了/dev/binder檔案,將binder_set_context_mgr命令傳給binder驅動的時候,binder驅動就會為其在核心空間中建立乙個節點(binder_node),
這個節點就是binder_context_mgr_node,也就是servicemanager的binder實體。
而這個節點所在的程序,就是servicemanager。
面試官突然間插了一句話,「那麼,你怎麼知道servicemanager在哪的?「
在整個系統中,只會有乙個binder_context_mgr_node,所以也只會有乙個servicemanager的程序,那麼對servicemanager的訪問,驅動就可以在系統中定義好其控制代碼,也就是 0。
所以只要是想找servicemanager的程序,只要告訴binder驅動,想訪問的是控制代碼為 0的程序,binder驅動就知道,它們是在找servicemanager。
它就會喚醒servicemanager,讓它接受訪問。
所以,"binder_set_context_mgr" 就是某某程序告訴驅動,它想成為servicemanager。而只要它是第乙個傳送這個命令的,它就是servicemanager了。
面試官好像稍微明白了一點,不過他想了一想,又問:」什麼是控制代碼?「
呃,這個我也不知道怎麼說,控制代碼理解上應該就是乙個區分不同服務的標識吧。不過在android系統中,只有跨程序的通訊,才會用到控制代碼這個術語,因為沒有辦法直接訪問。
而如果服務執行在本地程序中,由於共享同乙個程序空間,是可以直接訪問的,這個時候就不用控制代碼來描述了,而稱之為引用。
所以,控制代碼與引用的區別,就在於乙個是遠端訪問(跨程序),乙個是本地訪問(相同程序)。
面試官若有所思地看著面前這個人,目光中好像有那麼點懷疑的樣子,不過也就沒再繼續問下去。
但是他突然間又說了一句話,」你還沒有回答我,binder的機制是怎麼實現的呢,先簡單地說一下?「
通過上面的簡單描述,我們可以這樣認為,每乙個提供服務的server都會通過binder驅動,將自身給註冊到servicemanager中,方便眾多想獲取服務的client可以去servicemanager找到自己。
那麼,這些service都會經過核心空間的binder驅動,其實這個"經過"的說法,本質上,就是server們會將自身作為乙個物件,封裝在資料報中,將這些資料複製到核心空間中,由binder驅動訪問。
而binder驅動讀取資料報的時候,如果發現其中有binder實體,類似servicemanager那樣的服務提供商,那麼也會為對應的binder實體建立對應的binder節點(bindernode)。
這些節點位於server所屬的程序內。
binder驅動也會為這些服務分配控制代碼(大於0),同時會將這些控制代碼也記錄在binder驅動中,然後再將這些控制代碼和名字傳送給servicemanager,由servicemanager來維護。
也就是說,server們通過和binder驅動通訊,binder驅動做了如下兩件事:
1)在核心空間中建立了乙個binder節點,隸屬於server們的程序。
2)驅動為這些binder節點分配乙個大於0的包柄,將這些控制代碼和名字傳送給servicemanager。
那麼client們是怎麼和binder驅動通訊的呢?
很顯然,無論如何,client得知道要跟誰通訊,它們知道乙個名字。
所以,1)它們就會把想要獲取服務的名字,加上乙個控制代碼為 0 的值,封裝為乙個資料報,開啟binder裝置檔案,將這個資料傳送給binder驅動。
2)binder驅動接收到控制代碼為0,就會將這資料報扔給servicemanager。
3)servicemanager接收到這個資料報,就會分析,發現是要找某個名字的服務,於是就找找找,然後將對應服務的控制代碼傳送回來(某大於0的控制代碼)。
4)驅動再將這個控制代碼發回給client。
5)client獲取控制代碼之後,就會再加上想要的服務,還有這個控制代碼,再傳送給binder驅動,binder驅動就會找到對應的控制代碼,然後。。。。
面試官靜靜地坐在那裡,面無表情,也不知道在想什麼,最後說了一句,」先這樣,先回去吧,有結果會通知你的。「
跟面試官聊MySQL
目錄 你熟悉mysql嗎?mysql的整體架構是怎樣的?什麼是儲存引擎?mysql常用的儲存引擎有哪些?innodb和myisam有什麼區別?innodb索引的底層資料結構是怎樣的?為什麼不用b樹或者紅黑樹?說說你知道的索引吧。什麼情況下索引會失效?你知道mysql的隔離級別嗎?什麼是髒讀 不可重複...
面試官感悟
其實之前也面試過幾個人,但都是零星的跟著別人一起,我也只是偶爾詢問一兩句就結束了。昨天這是一場真正的大型招聘會,而且面試也是相當規範,面對的還是社招。對於我這種初出茅廬來說,這是第一次真正接觸參與的一場招聘會,想起要面那些比自己工作年限還長的人,心裡很沒底,有點小擔心和緊張的。當然一整天下來也算體驗...
面試官問題
解釋一些壓縮感知理論 壓縮感知是一種全新的訊號採集和恢復理論,它打破了傳統的奈奎斯特取樣定律,可以從更少的觀測訊號訊號中重建出高質量的原始訊號。其基本思想是,當訊號是稀疏或可壓縮時,我們可以通過乙個隨機測量矩陣將高維訊號投影到低維空間,再通過乙個求解優化問題高概率的恢復原始訊號。解釋一下壓縮感知磁共...