作者:鴻洋
前言
對Binder學習感興趣的小夥伴可以看看,希望能幫助到你們。
爲什麼會有Binder通信機制,爲什麼不能用linux中已有的進程框架呢?Google工程師究竟是如何考量的?
這一切可以通過一場戀愛來理解?
瞭解binder之前我們看看原有Linux進程是如何通信的吧!爲什麼需要在內存中拷貝兩次呢?
在瞭解Linux進程通信前我們先理解下 戀愛的故事吧!
故事:
男孩和女孩在某次旅遊一見鍾情,而旅行結束的他們不得不返回各自的工作城市
那個時代還沒有微信,由於相隔在不同的城市。相思的他們只能通過郵局抒發彼此愛慕之情
如果男孩想要給女孩發送信封,需要向本地郵局 寄信。再有全國郵局轉發到 女孩所在的本地郵局
最後由本地郵局送到女孩手中
在進程中的角色:
男孩 稱爲進程A,工作城市A城,女孩稱爲進程B,工作城市B城
本地郵局稱爲用戶空間, 全國郵局稱爲內核空間
本地郵局是他們離的最近的地方。他們可以接觸到本地郵局,可以在郵局中直接收信和發信
1.1 這是普通linux進程通信的方式
轉換專業術語的圖
進程間,用戶空間的數據不可共享(本地郵局是男孩或女孩獨有),所以用戶空間相當於私有空間。
進程間,內核空間的數據可共享(全國郵局是所有人共有),所以內核空間 相當於公共空間。
進程間如果需要做到通信,需要通過共享空間對數據轉換。轉換過程需要調用系統的api,這個過程稱爲系統調用。
問題來了:
男孩寫好信之後,發送信件給本地郵局 , 相當於一次拷貝 我們把這個過程稱爲(copy_from_user)
女孩收到當地郵局通知,需要從本地郵局取信。相當於第二次拷貝,我們把這個過程稱爲(copy_to_user)
這就是Linux已有進程間通信方式。
兩次拷貝究竟性能怎麼樣,當然拷貝是非常耗性能的,而兩次拷貝可以再優化優化。
那binder是怎麼做到一次拷貝的呢
1.2接着講愛情的例子(Binder的實現機制)
後來在疫情結束後,這個女孩去了全國郵局依賴的快遞公司上班去了,所有的信封需要用快遞公司來處理,剛好這家快遞公司處理的是他們兩個城市的信件。
爲了方便收信封,居然還有這操作
這就給女孩創造了便利,不用去本地郵局取信件
但是男孩還是要發送信件。binder拷貝也是發生在男孩這個地方copyfromuser,女孩由於在快遞公司上班,可以隨意瀏覽男孩的信件。不需要再取信件了。也就減少了從本地郵局取快遞這次拷貝過程
思考: 大家還記不記得接收端怎麼寫的,對! 接收端一定必須是服務Service,接收端不能是其他java對象。Service就是那個女孩。她必須在快遞公司上班才能減少一次拷貝。所以這個Service,在通信前會註冊在ServiceManager中。而男孩可以是任意對象,出現在任意地方。
Linux 已有的進程通信,發送端和接收端可以是任意對象。出現在任意類中。但是必須犧牲多拷貝一次
Android的Binder通信,接收端不能是任意對象,只能是Service,這也節約了一次拷貝,犧牲了開發者的體驗
1.3 Binder少拷貝一次的原理:
全國郵局 相當於內核空間的內存,所有的應用都與內核空間的內存發生頻繁的調用,在Binder中傳遞數據本質上是通過文件讀取來實現的
大家記不記得Linux系統 是文件操作系統,都是基於文件展開的。進程通信中 File也能實現進程通信
Binder機制中 在內存與文件中設計了一層映射關係。內核空間的內存是虛的,文件IO是實的。映射指的是內存與文件的映射,映射是通過mmap函數。
而mmap函數 需要依賴一個文件,這個文件叫做“binder”。對!他沒有後綴名,他就是一個文件。但是人們習慣性的把它稱爲binder驅動。
我們再來看看實際的是如何映射的
全國郵局中的A城與B城的信件,相當於內核空間內存一部分虛擬內存區域。
A城與B城的快遞公司,相當於文件實體。實際信封是由快遞公司轉發。郵局與快遞公司的合作關係,可以理解內存與文件形成了映射關係(mmap)
1.4 服務端Service 也通過mmap函數監聽文件的變化。
一旦有信件到達女孩的公司直接讀取出來,而不用去本地郵局取信件。
女孩怎麼在公司取出來呢?大家忘記了女孩在快遞公司上班呢,快遞公司會給員工佈置工作內容
女孩的工作內容是查看快遞接收站和發送站的信封
這樣你說能不能看到男朋友發過來的信件,還不用親自跑到本地郵局,那不是爽歪歪
綠色部分 是女孩進程,綠色內有兩個角色(女孩接觸到的 接收站和收發站)
這一套機制的實現基於 aidl文件編譯機制
在編譯時生成了一個繼承自Binder中的IInterface接口(女孩)。接口中有這樣一個內部類叫Stub(女孩工作接觸的接收站)和一個內部類叫Proxy(女孩工作接觸的發送站)
男孩信封到了,女孩直接在 快遞接收站查看男孩發過來的信封(Stub中的 onTransact方法)
女孩思戀男孩,給男孩發送信封(Proxy中的transact方法)
Stub與Proxy中所有的方法是native直接調用過來的。參數是直接從內核空間傳遞過來的,不需要發生拷貝。
如果女孩需要給男孩發送消息,也不用跑到本地郵局,直接在 快遞發送站,插入一個信封就好了(調用Proxy的transct方法)
減少一次拷貝發生在 服務端service。直接由nativie層 的Binder調起。不需要再次拷貝。
大家看完了 是不是對整個Binder機制有深刻的認識呢?
如果還不是很理解的,可以來看一下我搜集的一些關於Binder的詳細系統的學習資料和視頻從爲什麼會有Binder,到Binder原理,最後從Binder中mmap函數 能爲實際工作中解決儲存的問題。
從Binder的底層原理分析,讓Android開發者真正瞭解到Binder的通信機制。從Linux進程通信技術認知到爲什麼Android會選擇Binder作爲通信方式,到Linux的進程原理,最後借鑑Binder中mmap函數打造優異的存儲框架。
有需要的小夥伴可以私信我【Binder】我分享給你
希望在2020 資本寒冬和疫情的情況下,大家都能抓住這次機會,在這段時間內努力提升自己技術,把自己變得更優秀,成爲不可替代的人。最後找到自己滿意的工作。
330頁Android進階核心筆記
精選Binder進階視頻
B站賬號:bili_84936792704 希望資料加視頻可以提高大家學習的效率。