淺談 Firefox OS 的多程序架構與程序間通訊

作者:
瀏覽:379

FireFox OS 作為一個基於 Web 技術的作業系統,提供了許多 Web API 讓 app 開發人員可以存取手機的硬體、系統與個人資訊,然而這也帶來新的安全性的挑戰。為了降低系統弱點被利用的損害與增進系統安全性,FireFox OS 將每一個 app 執行在獨立程序 (process) 之中,app 所擁有的權限非常有限,例如不能開啟系統檔案系統或硬體裝置,需要存取系統資訊或硬體時都經由 IPC (inter-process communications) 向核心程序 (chrome process [1]) 請求,核心程序只會允許具有權限的 app 所提出的請求,如此可以避免單一 app 遭遇攻擊而影響其他 app 的運作或存取敏感資訊。

要看到 FireFox OS 系統中有哪些程序在執行,可以在手機 shell 中執行 b2g-ps 指令,系統就會列出 FireFox OS 的程序清單,如下圖:

root@android:/ # b2g-ps APPLICATION USER PID PPID VSIZE RSS WCHAN PC NAME b2g root 780 576 198760 88148 ffffffff 4010b330 S /system/b2g/b2g Homescreen app_860 860 780 91100 34932 ffffffff 40104330 S /system/b2g/plugin-container Settings app_916 916 780 90048 33888 ffffffff 4010d330 S /system/b2g/plugin-container Browser app_1018 1018 780 93212 35928 ffffffff 400c7330 S /system/b2g/plugin-container

圖中可以看到核心程序 b2g 與 Homescreen、Settings、Gallery 三個 app,b2g 程序是 app 程序們的父程序 (parent process) ,以 root 身分執行,而 app 程序們以較低的身分執行。而從 /proc 檔案系統中我們可以看到 app 程序和核心程序的 IPC 管道,app 和核心程序間以一組 unix domain socket 進行溝通,而訊息的收送則使用 IPDL (Inter-(process/thread)-communication Protocol Definition Language) 描述檔所產生的 C++ 程式碼負責。例如進行硬體存取的 IPDL 描述檔 PHal.ipdl 中 [2]

child: NotifySensorChange(SensorData aSensorData);

parent: EnableSensorNotifications(SensorType aSensor); DisableSensorNotifications(SensorType aSensor);

表示 child 端 (app 程序) 可以對 parent 端 (核心程序) 發出 EnableSensorNotifications/DisableSensorNotifications 的需求去開關某個感應器的通知,而 parent 端可以對 child 發出 NotifySensorChange 的訊息告知感應器的數值變化。另外在 JavaScript 中則可以透過 message manager 在核心與 app 程序間傳輸 JSON 訊息 [3].

多程序架構的程式在 debug 上相較於單程序的程式更具挑戰性,因為程式可能執行到特定的地方就進行 IPC 交由另一個程序去運作,要追蹤程式的運行需要同時追蹤多個程序。FireFox OS 上提供了一個環境變數方便我們去看核心和 app 程序之間傳送了哪些 IPC 訊息,要啟動 IPC 的 log ,首先要把 b2g 停掉

adb shell root@android:/ # stop b2g

之後加上環境變數 MOZ_IPC_MESSAGE_LOG,再從 shell 中啟動 FireFox OS:

root@android:/ # export MOZ_IPC_MESSAGE_LOG=1 root@android:/ # b2g.sh (中間略) [time:1365410665694116][916][PContentChild] Sending Msg_AsyncMessage([TODO]) [time:1365410665701592][916][PContentChild] Sending Msg_SyncMessage([TODO]) [time:1365410665702599][780][PContentParent] Received Msg_AsyncMessage([TODO]) [time:1365410665710229][780][PContentParent] Received Msg_SyncMessage([TODO]) [time:1365410665716943][780][PContentParent] Sending reply Reply_SyncMessage([TODO]) [time:1365410665718224][916][PContentChild] Received reply Reply_SyncMessage([TODO]) [time:1365410665739037][916][PIndexedDBDatabaseChild] Sending Msg_PIndexedDBTransactionConstructor([TODO]) [time:1365410665741174][780][PIndexedDBDatabaseParent] Received Msg_PIndexedDBTransactionConstructor([TODO]) (以下略)

如此就可以看到 Parent 跟 Child 分別傳送了什麼訊息,這樣遇到 IPC 方面的問題可以更容易去找到問題點。

[1] 參照 Chrome 的意義 ,注意 chrome 跟 Google Chrome 瀏覽器沒有關係,在這裡指的是具有 chrome privlege,在 Firefox OS 中就是 main process (b2g)。
[2] http://mxr.mozilla.org/mozilla-b2g18/source/hal/sandbox/PHal.ipdl#180
[3] https://developer.mozilla.org/en-US/docs/The_message_manager