原創 宋寶華 Linux閱碼場 2018-05-29
本系列2012年的時候發表在我的blog上面,現搬到公衆号
接上回:
Android架構縱橫談之——軟體自愈能力 (1)
上回書(Android架構縱橫談之——軟體自愈能力 (1))我們說到Android裡的init會監測init.rc中啟動的service并根據情況重新開機之。今回書我們說Android中生死與共的Zygote和SystemServer。
第二隻狗:忠犬八公
本回書,我們說第二隻狗,忠犬八公。1925年5月,八公的主人上野因病猝然去世,然而八公犬并不懂人事,依然每天到澀谷站去等候主人的歸來。直到最後死去。1935年3月,八公因患絲蟲性象皮病而死亡。十年生死兩茫茫,不思量,自難忘。所謂愛者,大抵如此。在這個小三流行的世界,什麼樣的人還珍視婚姻的責任和當初的誓言?

本回書我們要談的是Zygote和SystemServer的生死與共,執子之手,與子偕老,Zygote和SystemServer用全部的生命來演繹這段忠貞的愛情,當死去時,與子成蝶,如果有來生,我們還在一起。
Zygote是Android系統的核心,受精卵的意思,Android framework大家族的祖先。她的媽貴姓呢?就是上回書裡說的init。Zygote是Java世界的生産者,Android的女娲,她通過runSelectLoopMode()不斷監聽來自應用程式的透過ActivityManagerService的啟動需求,并fork出相應的程序。而SystemServer是Android世界裡的核心價值,SurfaceFlinger以及Java服務如PowerManagerService、 WindowManagerService、ActivityManagerService等都是他啟動的,并成為他的一部分,他帶的嗷嗷叫的兵,共同運作于SystemServer程序空間。可以說,SystemServer的崩潰基本意味着Android的Framework的崩潰。SystemServer是Android裡兵馬大元帥。基本上,在Android的世界裡,能與SystemServer和Zygote彼此相配的,也就隻有對方。那麼SystemServer百戰而死後,Zygote應該是萬念俱灰,其實真地沒有活着的必要。
在Android中,SystemServer是由 Zygote分叉出來的,相關代碼位于dalvik/vm/native/dalvik_system_Zygote.c中:
其中的forkAndSpecializeCommon()會fork出SystemServer,Zygote馬上用waitpid(pid, &status,WNOHANG)等待SystemServer的死亡,注意其中的參數為WNOHANG,意思就是說等不等地到SystemServer退出,waitpid()都不會阻塞,如果發現SystemServer死了,它會無條件調用kill(getpid(), SIGKILL)殉情。這個瞬間的等待按照注釋是為了防止很小的一段時間視窗裡,真正等SystemServer死的代碼還沒注意到SystemServer的PID。SIGKILL牛就牛在是不能被忽略的信号,這點和CTRL+C對應的SIGINT不同。
有些同學就要問了,一個程序莫名其妙地kill掉了自己,有時候我們還強行用kill指令去殺死Linux的程序,這個時候它原本申請的記憶體什麼的,不是洩露了嗎?譬如我malloc了一些記憶體,你殺死我的時候我還沒free,這些記憶體不是側露了嗎?我已經反複在各個公司演講的時候說了,記憶體洩露分為兩種境界,一個是人死了,錢還沒花完,你malloc的記憶體還沒釋放程序就死了,我們說,這個問題在Linux不存在,程序是個資源封裝的機關,程序挂的時候,資源會被核心釋放掉的,死的時候還僅僅有個僵屍而已。第二個境界是,人活着,錢沒了,這個問題才是Linux真正擔心的,一個多線程的程式,運作過程中反複申請和釋放記憶體,但是釋放的與申請的不對應,就慢慢地吃記憶體,這個程序的記憶體消耗曲線振蕩上升,直到耗盡記憶體。
是以,在Linux世界裡,我們不用擔心人死了,錢還沒花完的問題 。我們要擔心的是,人活着,錢沒了的問題。
說HTC Android手機号稱的1秒快速啟動,根據我們的跟蹤就是關機時候殺程序,然後suspend,之後resume回來,由于前面程序都殺了,是以你看到個幹淨的桌面。是以,神馬都是浮雲啊。
廢話少說,你剛才還說Zygote和SystemServer 生死與共,怎麼就才等了一下呢?不是要負責一輩子的嗎?我們回到forkAndSpecializeCommon(),繼續挖掘:
其中的setSignalHandler()會設定SIGCHLD的信号處理函數,而這個信号處理函數就會判斷是否SystemServer死了,如果是,就自殺殉情:
當SystemServer死去,Zygote的花轎在它墳前路過,見Zygote走出轎來,脫去紅裝,一身素服,緩緩地走到墳前, 跪下來放聲大哭,霎時間風雨飄搖,雷聲大作,“轟”的一聲,墳墓裂開了,Zygote似乎又見到了SystemServer那溫柔的面龐,她微笑着縱身跳了進去。接着又是一聲巨響,墳墓合上了。這時風消雲散,雨過天晴,各種野花在風中輕柔地搖曳,一對美麗的蝴蝶從墳頭飛出來,在陽光下自由地翩翩起舞。
當Zygote也死去,由于Zygote是有戶口的,上回書中的第一隻狗, 肩負其使命,會重新開機Zygote,于是SystemServer也随Zygote重新開機,生生世世不分離。
這裡要特别說明的是,當zygote死去的時候,上回書中的init中的wait_for_one_process()會透過給 “- zygote_pid”發SIGKILL,進而殺死Zygote對應的程序組,是以整個Java世界都宣告結束:
由于幾乎所有的Java應用都依賴于SystemServer中的service,如果SystemServer崩潰,Zygote不死并且不導緻整個Java世界死亡,實際上系統沒有任何辦法把狀态恢複到SystemServer崩潰之前的狀态 ,那麼各個apk所看到的SystemServer中各個service的狀态也無法恢複,是以整個Java世界死亡并重新開機就成為唯一的選擇。
本回書就說到這裡,下回書我們說SystemServer的看門狗。欲知後事如何,請聽下回分解。
謹以本回,獻給全天下的有情人,願有情人終成眷屬。對金錢與物質的無限度的追求,讓我們迷失了方向,而真正的幸福,是與你的夫妻平凡的終生相守。
相思似海深,舊事如天遠。
淚滴千千萬萬行,更使人、愁腸斷。
要見無因見,拚了終難拚。
若是前生未有緣,待重結、來生願。
(請聽下回分解)