上回書(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的看門狗。欲知後事如何,請聽下回分解。
謹以本回,獻給全天下的有情人,願有情人終成眷屬。對金錢與物質的無限度的追求,讓我們迷失了方向,而真正的幸福,是與你的愛人平凡的終生相守。
相思似海深,舊事如天遠。
淚滴千千萬萬行,更使人、愁腸斷。
要見無因見,拚了終難拚。
若是前生未有緣,待重結、來生願。
(請聽下回分解)