Zygote通信為什么用Socket蛋铆,而不是Binder?

我覺得馋评,chatgpt的答案好像更適合答題。
為什么zygote使用socket而不是binder

Zygote是Android中的一個重要進(jìn)程刺啦,它是啟動應(yīng)用程序進(jìn)程的父進(jìn)程留特。Zygote使用Socket來與應(yīng)用程序進(jìn)程進(jìn)行通信,而不是使用Android中的IPC機(jī)制Binder玛瘸,這是因為Socket和Binder有不同的優(yōu)缺點(diǎn)蜕青,而在Zygote進(jìn)程中使用Socket可以更好地滿足Zygote進(jìn)程的需求。

首先糊渊,Socket具有良好的跨平臺性右核,能夠在不同的操作系統(tǒng)和語言之間進(jìn)行通信。這對于Zygote進(jìn)程來說非常重要渺绒,因為它需要在不同的設(shè)備和架構(gòu)上運(yùn)行贺喝,并且需要與不同的應(yīng)用程序進(jìn)程進(jìn)行通信。使用Socket可以讓Zygote進(jìn)程更加靈活和可擴(kuò)展宗兼,因為它不需要考慮Binder所帶來的特定限制和要求躏鱼。

其次,Socket具有簡單的API和易于使用的特點(diǎn)针炉。Zygote進(jìn)程需要快速啟動并與應(yīng)用程序進(jìn)程建立通信挠他,Socket提供了快速、可靠的通信方式篡帕,并且使用Socket API也很容易實(shí)現(xiàn)殖侵。相比之下,Binder需要更多的配置和維護(hù)工作镰烧,這對于Zygote進(jìn)程來說可能會增加不必要的復(fù)雜性和開銷拢军。

最后,Socket在數(shù)據(jù)傳輸時具有更低的延遲和更高的吞吐量怔鳖,這對于Zygote進(jìn)程來說非常重要茉唉。Zygote進(jìn)程需要在較短的時間內(nèi)啟動應(yīng)用程序進(jìn)程,并且需要傳輸大量的數(shù)據(jù)和代碼,Socket的高性能和低延遲使其成為更好的選擇度陆。

總之艾凯,Zygote進(jìn)程使用Socket而不是Binder是基于其優(yōu)點(diǎn)和需求而做出的選擇。雖然Binder在Android中扮演著重要的角色懂傀,但在某些情況下罩息,使用Socket可以提供更好的性能和更大的靈活性枣察。
——分割線——
看完《安卓傳奇:Android締造團(tuán)隊回憶錄》后,我覺得這個問題的答案書中給出了.這段歷史是這樣的...
先來看看書中關(guān)于Zygote的靈感來源,Emacs.

是Dalvik小組為Android 1.0 開發(fā)的另一個東西笛粘。Zygote就像你做三明治時用的面包片外臂。當(dāng)然,你也可以在每次做三明治時從頭開始烤面包犀斋,但如果是這樣的話贝乎,每次你想吃三明治都要花大量的時間和精力。很明顯叽粹,如果有現(xiàn)成的面包览效,你只需要把它切成片,并更快更容易地做出三明治球榆。Zygote就像做三明治用的面包朽肥。
Dan的這個想法來自Emacs(UNIX系統(tǒng)上的一個非常流行的文本編輯器)的一個特性,我們可以隨時轉(zhuǎn)儲編輯器的狀態(tài)持钉,稍后可以從這個保存點(diǎn)啟動Emacs(這個過程被巧妙地稱為反轉(zhuǎn)儲(undump))衡招。這意味著Emacs可以更快地啟動,因為它只需要從磁盤上恢復(fù)狀態(tài)每强,
不需要在啟動時重新執(zhí)行一大堆代碼邏輯始腾。“我的想法是我們實(shí)現(xiàn)一個具有反轉(zhuǎn)儲功能的系統(tǒng)空执,就像Emacs最‘著名’(至少對我來說)的那個特性浪箭。Mike Fleming說:‘我們跳過轉(zhuǎn)儲和重新加載這些步驟,怎么樣辨绊?’說完他就開干了奶栖。”
Mike 讓系統(tǒng)跑了起來门坷,從根本上改變了應(yīng)用程序的啟動方式宣鄙。原先的每個應(yīng)用程序在啟動時都需要加載必要的代碼,并進(jìn)行初始化默蚌。Zygote 創(chuàng)建了一個包含大部分核心平臺代碼的進(jìn)程冻晤,并幾乎預(yù)加載和初始化了所有這些代碼。每當(dāng)有應(yīng)用程序啟動時绸吸,都會通過分叉
(將其復(fù)制到一個新進(jìn)程中)Zygote 進(jìn)程鼻弧,讓應(yīng)用程序立即進(jìn)入即將就緒的狀態(tài)设江。

而binder的來源.

Binder 的概念可以追溯到 Be 公司。George Hoffman 是 Be 公司圖形和框架團(tuán)隊的負(fù)責(zé)人攘轩,他需要一種機(jī)制讓 Be 的互聯(lián)網(wǎng)設(shè)備的 JavaScript UI 層與底層系統(tǒng)服務(wù)發(fā)生交互叉存,于是就有了 Binder。隨著 Be 公司的工程師后來加入 PalmSource 開發(fā) Palm OS度帮,再到后來加入 Android鹉胖,Binder 也都一直在演化。George 最終沒有參與開發(fā) Android够傍,但他與 Be 和 PalmSource 的未來 Android 工程師一起設(shè)計了許多概念,這些概念最終都出現(xiàn)在 Android 上挠铲,比如 Activity 和 Intent冕屯。
Android 設(shè)備上始終運(yùn)行著許多進(jìn)程,負(fù)責(zé)處理系統(tǒng)的各種任務(wù)拂苹。系統(tǒng)進(jìn)程負(fù)責(zé)進(jìn)程的管理安聘、應(yīng)用的啟動、窗口的管理和其他底層的操作系統(tǒng)功能瓢棒。電話進(jìn)程負(fù)責(zé)保持通話正常連接浴韭。運(yùn)行中的前臺應(yīng)用進(jìn)程為用戶提供交互功能。系統(tǒng) UI 進(jìn)程負(fù)責(zé)處理導(dǎo)航按鈕脯宿、狀態(tài)欄和通知念颈。還有很多其他進(jìn)程,它們都需要在某個時刻與其他流程通信连霉。
通常來說榴芳,IPC 機(jī)制是一種簡單而底層的東西,而這也正是 Danger 前工程師們想要的跺撼。
黃威說:“Danger 做事喜歡速戰(zhàn)速決窟感,但主要還是要簡單∏妇”但來自 Be 公司的工程師柿祈,包括 Jeff、Joe 和 Dianne哩至,更喜歡他們在 PalmSource 實(shí)現(xiàn)的功能更全面(也更復(fù)雜)的 Binder躏嚎。
況且,Binder 是開源的憨募,可以直接用在這個新平臺上紧索。
這一分歧造成了團(tuán)隊之間的摩擦。Mike Fleming 站在 Danger 一邊:“我對 Binder 持懷疑態(tài)度菜谣。我認(rèn)為它沒有經(jīng)過深思熟慮珠漂。這確實(shí)是他們在 Palm 做的晚缩,但并沒有被用在真正的產(chǎn)品中∠蔽#”
“我感覺特別糟糕的是對Binder的阻塞調(diào)用會導(dǎo)致另一邊也阻塞荞彼。我覺得這導(dǎo)致了很多不必要的線程開銷,而且沒有為我們帶來任何價值待笑。另外鸣皂,初始的Binder Linux內(nèi)核驅(qū)動程序也不是很健壯。為了讓它更健壯暮蹂,我們也是費(fèi)了很大一番功夫的寞缝。”
對Binder持懷疑態(tài)度的人并沒有贏得這場戰(zhàn)斗仰泻,Jeff和他的小組奮勇向前荆陆,實(shí)現(xiàn)了Binder,成為Android框架的一個基礎(chǔ)部分集侯。與此同時被啼,Mike在他的電話功能中跳過Binder:“我在Java進(jìn)程和本地接口進(jìn)程之間開了一個UNIX域套接字√耐鳎”

binder當(dāng)初并不成熟,團(tuán)隊成員對于進(jìn)程間通訊更傾向于用socket.后面為了做了很多優(yōu)化,才使得binder通訊變得成熟穩(wěn)定.
關(guān)于Android操作系統(tǒng),書中推薦閱讀《現(xiàn)代操作系統(tǒng)》浓体,并深入閱讀介紹 Android 的章節(jié)(10.8)。那一章是 Dianne Hackborn 寫的辈讶,為 Binder和 Linux 擴(kuò)展等內(nèi)容提供了詳盡的細(xì)節(jié)命浴。另關(guān)于handle設(shè)計思想的理解,我推薦閱讀《C++沉思錄》.

----------分割線---------

要想了解這個問題,首先需要對Linux進(jìn)程間通訊機(jī)制有一定的了解荞估。

1.Linux進(jìn)程間通訊機(jī)制

https://www.zhihu.com/question/39440766/answer/89210950
Linux現(xiàn)有的所有進(jìn)程間IPC方式:
1.管道:在創(chuàng)建時分配一個page大小的內(nèi)存咳促,緩存區(qū)大小比較有限;
2.消息隊列:信息復(fù)制兩次勘伺,額外的CPU消耗跪腹;不合適頻繁或信息量大的通信;
3.共享內(nèi)存:無須復(fù)制飞醉,共享緩沖區(qū)直接付附加到進(jìn)程虛擬地址空間冲茸,速度快;但進(jìn)程間的同步問題操作系統(tǒng)無法實(shí)現(xiàn)缅帘,必須各進(jìn)程利用同步工具解決轴术;
4.套接字:作為更通用的接口,傳輸效率低钦无,主要用于不通機(jī)器或跨網(wǎng)絡(luò)的通信逗栽;
5.信號量:常作為一種鎖機(jī)制,防止某進(jìn)程正在訪問共享資源時失暂,其他進(jìn)程也訪問該資源彼宠。因此鳄虱,主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段
6.信號: 不適用于信息交換,更適用于進(jìn)程中斷控制凭峡,比如非法內(nèi)存訪問拙已,殺死某個進(jìn)程等;

Binder機(jī)制基于開源的OpenBinder摧冀。http://www.angryredplanet.com/~hackbod/openbinder/docs/html/BinderIPCMechanism.html

2. socket 與 binder 對比

先來看看 socket與binder 兩種進(jìn)程間通訊機(jī)制 對比倍踪。


http://www.reibang.com/p/066d99da7cbd
http://gityuan.com/2015/11/21/binder-framework/

接下來回顧下 Zygote啟動和Android啟動。
Zygote啟動過程的函數(shù)調(diào)用類大致流程:


http://gityuan.com/2016/02/13/android-zygote/#jnistartreg

http://gityuan.com/2016/02/13/android-zygote/#jnistartreg
Zygote啟動過程:
1.解析init.zygote.rc中的參數(shù)索昂,創(chuàng)建AppRuntime并調(diào)用AppRuntime.start()方法建车;
2.調(diào)用AndroidRuntime的startVM()方法創(chuàng)建虛擬機(jī),再調(diào)用startReg()注冊JNI函數(shù)椒惨;
3.通過JNI方式調(diào)用ZygoteInit.main()癞志,第一次進(jìn)入Java世界;
4.registerZygoteSocket()建立socket通道框产,zygote作為通信的服務(wù)端,用于響應(yīng)客戶端請求错洁;
5.preload()預(yù)加載通用類秉宿、drawable和color資源、openGL以及共享庫以及WebView屯碴,用于提高app啟動效率描睦;
6.zygote完畢大部分工作,接下來再通過startSystemServer()导而,fork得力幫手system_server進(jìn)程忱叭,也是上層framework的運(yùn)行載體。
7.zygote功成身退今艺,調(diào)用runSelectLoop()韵丑,隨時待命,當(dāng)接收到請求創(chuàng)建新進(jìn)程請求時立即喚醒并執(zhí)行相應(yīng)工作虚缎。

下面來看一張圖撵彻,標(biāo)示了調(diào)用startService之后的通訊流程。

http://gityuan.com/2016/03/06/start-service/

圖中涉及3種IPC通信方式:Binder实牡、Socket以及Handler陌僵,在圖中分別用3種不同的顏色來代表這3種通信方式。一般來說创坞,同一進(jìn)程內(nèi)的線程間通信采用的是 Handler消息隊列機(jī)制碗短,不同進(jìn)程間的通信采用的是binder機(jī)制,另外與Zygote進(jìn)程通信采用的Socket题涨。

Android系統(tǒng)啟動流程如下:


http://www.reibang.com/p/3e033aeb44f8

現(xiàn)在回到問題偎谁,為什么Zygote通信為什么用Socket总滩,而不是Binder?

具體可看這篇:
android中AMS通知Zygote去fork進(jìn)程為什么使用socket而不使用binder?

可從以下五個方面分析:
1.先后時序問題:
binder驅(qū)動是早于init進(jìn)程加載的搭盾。而init進(jìn)程是安卓系統(tǒng)啟動的第一個進(jìn)程咳秉。
安卓中一般使用的binder引用,都是保存在ServiceManager進(jìn)程中的鸯隅,而如果想從ServiceManager中獲取到對應(yīng)的binder引用澜建,前提是需要注冊。雖然Init進(jìn)程是先創(chuàng)建ServiceManager蝌以,后創(chuàng)建Zygote進(jìn)程的炕舵。雖然Zygote更晚創(chuàng)建,但是也不能保證Zygote進(jìn)程去注冊binder的時候跟畅,ServiceManager已經(jīng)初始化好了咽筋。注冊時間點(diǎn)無法保證,AMS無法獲取到Zygote的binder引用徊件,這是原因之一奸攻。

http://www.reibang.com/p/3f3f8a5bbc6b

2.多線程問題
Linux中,fork進(jìn)程是不推薦fork一個多線程的進(jìn)程的虱痕,因為如果存在鎖的情況下睹耐,會導(dǎo)致鎖異常。
而如果自身作為binder機(jī)制的接收者部翘,就會創(chuàng)建一個額外的線程來進(jìn)行處理(發(fā)送者進(jìn)程是無影響的)硝训。
所以,如果使用binder機(jī)制新思,就會導(dǎo)致去fork一個多線程的進(jìn)程窖梁,這是原因之二。

3.效率問題
AMS和Zygote之間使用的LocalSocket夹囚,相對于網(wǎng)絡(luò)Socket纵刘,減少了數(shù)據(jù)驗證等環(huán)節(jié),所以其實(shí)效率相對于正常的網(wǎng)絡(luò)Socket會大幅的提升荸哟。雖然還是要經(jīng)過兩次拷貝彰导,但是由于數(shù)據(jù)量并不大,所以其實(shí)影響并不明顯敲茄。
所以位谋,LocalSocket效率其實(shí)也不低,這是原因之三堰燎。

4.安全問題
LocalSocket其實(shí)也有權(quán)限校驗掏父,并不意味著可以被所有進(jìn)程隨意調(diào)用,這是原因之四秆剪。

5.Binder拷貝問題
如果使用binder通訊機(jī)制的話赊淑,從Zygote中fork出子進(jìn)程會拷貝Zygote中binder對象爵政。所以就憑白多占用了一塊無用的內(nèi)存區(qū)域。而Binder對象不能釋放陶缺。Binder的特殊性在于其是成對存在的钾挟,其分為Client端對象和Server端對象。假設(shè)我們使用binder饱岸,如果要釋放掉APP的Server端binder引用對象掺出,就必須釋放掉AMS中的Client端binder對象,那這樣就會導(dǎo)致AMS失去binder從而無法正常向Zygote發(fā)送消息苫费。
而使用socket通訊機(jī)制的話汤锨,fork出APP進(jìn)程之后,APP進(jìn)程會去主動的關(guān)閉掉這個socket百框,從而釋放這塊區(qū)域闲礼。相關(guān)代碼在ZygoteConnection的processCommand方法中:

try {
            if (pid == 0) {
            // in child
            zygoteServer.setForkChild();
 
            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
 
            return handleChildProc(parsedArgs, childPipeFd,
                                    parsedArgs.mStartChildZygote);
            } else {
               // In the parent. A pid < 0 indicates a failure and will be handled in
               // handleParentProc.
               IoUtils.closeQuietly(childPipeFd);
               childPipeFd = null;
               handleParentProc(pid, serverPipeFd);
               return null;
            }
    } 

所以,使用binder會造成額外的內(nèi)存占用铐维,這是原因之五柬泽。

另外,binder調(diào)用一般是同步阻塞的嫁蛇。如果使用oneway聂抢,是非阻塞(像一些系統(tǒng)服務(wù)調(diào)用應(yīng)用進(jìn)程的時候就會使用 oneway,比如 AMS 調(diào)用應(yīng)用進(jìn)程啟動 Activity棠众,這樣就算應(yīng)用進(jìn)程中做了耗時的任務(wù),也不會阻塞系統(tǒng)服務(wù)的運(yùn)行有决。)闸拿。但是,binder驅(qū)動對于oneway的調(diào)用是類似于handler sendmessage那樣的书幕,挨個處理新荤,所以如果服務(wù)端的oneway接口處理太慢而客戶端調(diào)用太多的話,來不及處理的調(diào)用會占滿binder驅(qū)動的緩存台汇,導(dǎo)致其他調(diào)用拋出上面的transaction failed苛骨。
oneway 方法的隱患具體參考這篇。
AIDL oneway 方法的隱患

socket也不是單獨(dú)使用的苟呐,I/O模型中的epoll是一種高效的管理socket的模型痒芝,epoll機(jī)制相對成熟,是同步非阻塞牵素。

socket(套接字)是對 TCP/IP 或者UDP/IP協(xié)議的封裝,Socket本身并不是協(xié)議,而是一個調(diào)用接口(API)严衬。
而Binder很負(fù)復(fù)雜。

簡單的設(shè)計笆呆,減少出問題的幾率请琳,會讓系統(tǒng)更加穩(wěn)定粱挡。

Zygote通信為什么用Socket,而不是Binder?
說了這么多俄精,其實(shí)是通過對比加深對Android進(jìn)程間通訊Socket和Binder兩種機(jī)制的理解询筏。

3.Zygote 處理 socket消息代碼分析

具體代碼流程分析可看這篇:
app_process: zygote處理socket消息請求(5)

參考鏈接:
為什么 Android 要采用 Binder 作為 IPC 機(jī)制?
為什么Android的Zygote與SystemServer通信采用Socket竖慧,而不是Binder?
[026]Zygote中Socket通信能否替換成Binder通信嫌套?
Android系統(tǒng)啟動-zygote篇
Android10.0系統(tǒng)啟動之Zygote進(jìn)程-[Android取經(jīng)之路]
app_process: zygote處理socket消息請求(5)
Android Framework層學(xué)習(xí)——為什么SystemServer進(jìn)程與Zygote進(jìn)程通訊采用Socket而不是Binder
android中AMS通知Zygote去fork進(jìn)程為什么使用socket而不使用binder

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市测蘑,隨后出現(xiàn)的幾起案子灌危,更是在濱河造成了極大的恐慌,老刑警劉巖碳胳,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勇蝙,死亡現(xiàn)場離奇詭異,居然都是意外死亡挨约,警方通過查閱死者的電腦和手機(jī)味混,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诫惭,“玉大人翁锡,你說我怎么就攤上這事∠ν粒” “怎么了馆衔?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長怨绣。 經(jīng)常有香客問我角溃,道長,這世上最難降的妖魔是什么篮撑? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任减细,我火速辦了婚禮,結(jié)果婚禮上赢笨,老公的妹妹穿的比我還像新娘未蝌。我一直安慰自己,他們只是感情好茧妒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布萧吠。 她就那樣靜靜地躺著,像睡著了一般桐筏。 火紅的嫁衣襯著肌膚如雪怎憋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機(jī)與錄音绊袋,去河邊找鬼毕匀。 笑死,一個胖子當(dāng)著我的面吹牛癌别,可吹牛的內(nèi)容都是我干的皂岔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼展姐,長吁一口氣:“原來是場噩夢啊……” “哼躁垛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起圾笨,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤教馆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后擂达,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體土铺,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年板鬓,在試婚紗的時候發(fā)現(xiàn)自己被綠了悲敷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡俭令,死狀恐怖后德,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抄腔,我是刑警寧澤瓢湃,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站赫蛇,受9級特大地震影響绵患,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜棍掐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拷况。 院中可真熱鬧作煌,春花似錦、人聲如沸赚瘦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽起意。三九已至鹰服,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背悲酷。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工套菜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人设易。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓逗柴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親顿肺。 傳聞我的和親對象是個殘疾皇子戏溺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容