網站首頁 編程語言 正文
1.簡單介紹下binder
binder
是一種進程間通訊的機制
進程間通訊需要了解用戶空間
和內核空間
每個進程擁有自己的獨立虛擬機
,系統為他們分配的地址空間都是互相隔離
的。 如兩個進程需要進行通訊,則需要使用到內核空間
做載體,內核空間是所有進程共享
的一塊內存區域。 而用戶空間切到內核空間需要使用到系統api ioctl
進行通訊。內核獲取用戶的數據需要使用copy_from_user
,內核將數據發送給其他進程需要使用copy_to_user
,這兩個方法是有性能開銷
的,對于socket
就是使用的這種模式,為了減少這部分的開銷,內核提供了binder
,binder
只需要一次拷貝就可以實現進程通訊.
主要是使用mmap
的原理:
在內核空間
和用戶空間
都開辟一塊虛擬內存
區域同時指向一塊物理地址
,這樣內核需要傳遞數據給用戶空間時,只需要將數據拷貝
到對應的虛擬內存地址
中,用戶可以通過虛擬內存映射
關系,獲取到內核中的數據,實現了一次拷貝
通訊。
binder
架構上面使用的是C/S架構:
binder中有三要素: 客戶端,服務端和ServiceManager
binder
整體過程:
1.注冊服務 2.獲取服務 3.使用服務
2.Binder的定向制導,如何找到目標Binder,喚起進程或者線程?
數據結構流程:
1.server注冊過程 1.server傳入一個flat_binder_object給內核態。內核根據這個flat_binder_object創建binder_node節點,為每個進程服務,內部有個binder_proc.proc = server進程 2.serviceManager在內核態創建binder_ref引用這個binder_node,內部有一項desc = 1,2,3..,在用戶態會創建一個服務鏈表{name ="server name",handle = "server handle"} 2.client獲取服務過程 3.client向sm查詢服務,傳遞name 4.sm返回handle給驅動程序 5.驅動程序在sm的binder_ref_desc紅黑樹中根據handle找到binder_ref,再根據binder_ref.node找到binder_node,最后給client創建新的binder_ref指向這個binder_node,他的desc從1開始binder_ref{desc=1,node = binder_node},驅動返回desc給client,即handle總結:sm中的handle順序是根據服務注冊順序顯示,返回給client中的handle是根據服務獲取的順序顯示的 3.client使用handle過程 6.:驅動里面根據handle找到找到binder_ref,根據binder_ref找到binder_node,根據binder_node找到進程server
注:
flat_binder_object{ type:是binder實體還是引用,只有需要注冊的服務可以傳binder實體,其他只能傳handle引用 flag(聯合體) binder(實體:處理函數)/handle(引用:服務的引用): cookie }
數據傳輸過程(進程切換):
數據如何復制:
3.Binder中的紅黑樹,為什么會有兩棵binder_ref紅黑樹
-
refs_by_desc
主要是通過desc
來查找對應的binder_ref
-
refs_by_node
主要是通過node
來查找對應的binder_ref
查找方式不一樣
4.Binder一次拷貝原理
傳統的數據拷貝方式如socket
:
用戶空間---->內核空間:`copy_from_user ` 內核空間---->用戶空間:`copy_to_user`
而binder使用mmap
機制
在內核空間和用戶空間中間使用物理地址開辟了一個映射關系 內核空間調用copy_from_user會直接將數據拷貝到內核空間并反饋到映射后的物理地址上, 由于用戶空間和物理地址也有個映射關系,用戶空間可以直接通過映射的虛擬地址指針訪問到寫入物理地址的數據。 這就是binder一次拷貝的原理
5.Binder傳輸數據的大小限制?
對于內核
可以傳輸的是4M
,但是應用層
限制在1M-8K
范圍內,這就是在進程間傳輸過大的數據會導致崩潰
的原因
6.系統服務與bindService等啟動的服務的區別
系統服務
需要將服務注冊到ServiceManager
,使用的時候需要通過服務名稱去ServiceManger中獲取服務的引用,
而bindService
等啟動的服務是將服務注冊到AMS中的ServiceMap
中,所有的服務的生命周期
都由AMS
控制。啟動服務的進程如果需要使用IPC通訊,都是和獲取AMS
的代理類進行通訊,AMS
也是在SystemServer
啟動的時候一個注冊到ServiceManager
的系統服務。
7.Binder多線程
binder
線程池默認
提供了15
個線程進行處理進程間并發
事件,如果服務端線程不夠
用,則驅動會發出一個信號
,應用層收到這個信號調用Register_Thread
,這樣驅動層就可以使用這個新建
出來的子線程
進行數據的處理
8.Android APP進程天生支持Binder通信的原理是什么?
Android APP進程都是由Zygote進程孵化出來的。
常見場景:
點擊桌面icon
啟動APP
,或者startActivity
啟動一個新進程里面的Activity
,最終都會由AMS
去調用Process.start()
方法去向Zygote
進程發送請求,讓Zygote
去fork
一個新進程,Zygote
收到請求后會調用Zygote.forkAndSpecialize()
來fork
出新進程,之后會通過RuntimeInit.nativeZygoteInit
來初始化Andriod
APP運行需要的一些環境,而binder
線程就是在這個時候新建啟動的
virtual void onZygoteInit() { sp proc = ProcessState::self(); //啟動新binder線程loop proc->startThreadPool(); }
9.同一個線程的請求必定是順序執行,即使是異步請求(oneway)
一般而言,Client
同步阻塞請求Service
,直到Service
提供完服務后才返回,不過,也有特殊
的,比如請求用ONE_WAY
方式,這種場景一般主要是用來通知
,至于通知被誰消費,是否被消費壓根不會關心
。 拿ContentService
服務為例子,它是一個全局的通知中心
,負責轉發通知,而且,一般是群發,由于在轉發的時候,ContentService
被看做Client
,如果這個時候采用普通的同步阻塞勢必會造成通知的延時發送送,所以這里的Client
采用了oneway
,異步。
原文鏈接:https://juejin.cn/post/7114535605404434440
相關推薦
- 2022-09-16 JQuery實現電梯導航效果_jquery
- 2023-07-22 垃圾回收的核心知識點解析
- 2022-03-13 使用vs2022在.net6中調試帶typescript的靜態頁面_基礎應用
- 2022-04-14 C#可變參數params示例詳解_C#教程
- 2022-06-10 使用Android實現一個懸浮在軟鍵盤上的輸入欄_Android
- 2023-10-12 解決父元素opacity會影響子元素的問題
- 2023-12-20 SpringCloud服務無法注冊到Nacos的踩坑記錄
- 2022-07-26 論網頁檢查preview和response一個是漢字一個是亂碼怎么解決
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支