啟動 Fuchsia 模擬器

ffx emu 指令會在主機上啟動及管理 Fuchsia 模擬器。

概念

Fuchsia 模擬器 (也稱為 FEMU) 提供一種機制,可在不使用實體硬體裝置的情況下,開發及測試 Fuchsia 平台和產品。Fuchsia 模擬器是建構在 QEMU 上,這是一個開放原始碼機器模擬器和虛擬化工具。

QEMU 和 AEMU

Fuchsia 模擬器提供兩種模擬引擎:第一個是 Android Emulator (AEMU) 的擴充功能,第二個則是 QEMU 版本 (6.2.0 版)。AEMU 引擎主要用於涉及圖形的工作,因為 AEMU 支援 Vulkan 圖形程式庫。不過,最新的 AEMU (以 QEMU 2.12 分支為基礎建構而成) 缺少數個版本的上游修正、功能和效能強化項目。因此,如果工作流程不需要圖形,建議您在無頭模式下使用 QEMU 引擎。

啟動模擬器時,您必須指定下列資訊:

  • 用於做為後端的引擎。
  • 要模擬的虛擬裝置類型。
  • 要在虛擬裝置上執行的產品。

根據預設,ffx emu 指令會選取 AEMU 引擎,因為大多數工作都需要某種程度的圖形支援。目前,所有現有的產品套裝組合都只有一個虛擬裝置類型。

產品組合

兩個 FEMU 引擎都會使用一組 Fuchsia 映像檔和中繼資料,稱為產品套件。使用 Fuchsia SDK 時,您必須事先使用 ffx product download 指令擷取產品套件。產品套裝組合包含不同 CPU 架構的系統映像檔。每個系統映像檔都包含中繼資料 (例如在不同虛擬裝置上執行的硬體規格) 以及相關的系統套件。

網路

模擬器與其主機之間有三種網路模式可供選擇:

這些模式會使用 --net 旗標,並分別選取 tapusernone 選項。另外還有 --net auto 模式,如果未指定旗標,則預設為此模式。在 auto 模式中,模擬器會檢查主機上是否有 Tun/Tap 介面,如果有,模擬器會選取 --net tap 模式。但如果沒有,或 Tun/Tap 介面已處於忙碌狀態 (例如,該介面已連接至其他模擬器程序),模擬器就會選取 --net user 模式。

列出所有可用的產品組合

如要查看線上儲存空間中所有可用的產品套裝組合清單 (預設為 gs://fuchsia 的 Google Cloud Storage),請執行下列指令:

ffx --machine json-pretty product list --version <SDK_VERSION>

這個指令會輸出類似以下的輸出內容:

$ ffx --machine json-pretty product list --version 15.20230906.1.1
Progress for "Getting product descriptions"
  development/15.20230906.1.1/product_bundles.json
    1141 of 1141 bytes (100.00%)
[
  {
    "name": "core.vim3",
    "product_version": "15.20230906.1.1",
    "transfer_manifest_url": "gs://fuchsia-public-artifacts-release/builds/8770722574108649889/transfer.json"
  },
  {
    "name": "core.x64",
    "product_version": "15.20230906.1.1",
    "transfer_manifest_url": "gs://fuchsia-public-artifacts-release/builds/8770722574108649873/transfer.json"
  },
  {
    "name": "minimal.x64",
    "product_version": "15.20230906.1.1",
    "transfer_manifest_url": "gs://fuchsia-public-artifacts-release/builds/8770722574108649857/transfer.json"
  },
  {
    "name": "terminal.qemu-arm64",
    "product_version": "15.20230906.1.1",
    "transfer_manifest_url": "gs://fuchsia-public-artifacts-release/builds/8770722574108649841/transfer.json"
  },
  {
    "name": "terminal.x64",
    "product_version": "15.20230906.1.1",
    "transfer_manifest_url": "gs://fuchsia-public-artifacts-release/builds/8770722574108649809/transfer.json"
  }
]

下載產品組合

如要從線上儲存空間 (預設為 gs://fuchsia 的 Google Cloud Storage) 下載產品套件,請執行下列指令:

ffx product download <TRANSFER_MANIFEST_URL> <LOCAL_PATH>

下列範例指令會下載 minimal.x64 產品套件:

$ ffx product download gs://fuchsia-public-artifacts-release/builds/8770722574108649857/transfer.json ~/local_pb --force

這個指令會輸出類似以下的內容:

$ ffx product download gs://fuchsia-public-artifacts-release/builds/8770722574108649857/transfer.json ~/local_pb --force
Progress for "Transfer download"
  complete
    2 of 2 steps (100.00%)

這個指令可能需要幾分鐘才能下載圖片和產品中繼資料。

啟動 Fuchsia 模擬器

如要啟動 Fuchsia 模擬器,請執行下列指令:

ffx emu start PRODUCT_BUNDLE [--name NAME]

PRODUCT_BUNDLE 替換為主機上下載的產品套裝組合路徑。

以下範例指令使用 ~/local_pb 目錄啟動 Fuchsia 模擬器:

$ ffx emu start ~/local_pb

這個指令會輸出類似以下的內容:

$ ffx emu start ~/local_pb
Logging to "/home/alice/.local/share/Fuchsia/ffx/emu/instances/fuchsia-emulator/emulator.log"
Waiting for Fuchsia to start (up to 60 seconds).............................
Emulator is ready.

模擬器啟動後,指令會結束,但模擬器會繼續在背景執行。接著,系統會開啟另一個視窗,開始顯示輸入產品套件內含的 Fuchsia 系統圖形介面。

根據預設,Fuchsia 模擬器會以 fuchsia-emulator 的名稱啟動。不過,如要以不同名稱啟動 Fuchsia 模擬器 (例如需要啟動多個執行個體時),您可以使用 --name 旗標,例如:

$ ffx emu start ~/local_pb --name my-fuchsia-example-01

如要查看所有執行中模擬器執行個體的清單,您可以使用 ffx emu list 指令。

啟動不支援圖形功能的 Fuchsia 模擬器

根據預設,ffx emu start 指令會啟動 Fuchsia 模擬器,並開啟新視窗,顯示模擬器的圖形介面。不過,在某些情況下,您可能會選擇在模擬器例項上停用圖形支援功能,以便執行不需要視覺效果的作業,例如自動化測試。

如要在不使用圖形的情況下啟動 Fuchsia 模擬器,請執行下列指令:

ffx emu start PRODUCT_BUNDLE --headless [--engine qemu]

PRODUCT_BUNDLE 替換為主機上下載的產品套裝組合路徑。

以下範例指令使用 ~/local_pb 目錄啟動 Fuchsia 模擬器:

$ ffx emu start ~/local_pb --headless --engine qemu

這個指令會輸出類似以下的輸出內容:

$ ffx emu start ~/local_pb --headless --engine qemu
Logging to "/home/alice/.local/share/Fuchsia/ffx/emu/instances/fuchsia-emulator/emulator.log"
Waiting for Fuchsia to start (up to 60 seconds).............................
Emulator is ready.

這個指令會照常在背景啟動 Fuchsia 模擬器的執行個體,但主機機器的螢幕上不會顯示其圖形介面。

列出所有執行中的模擬器例項

如要查看主機上執行中的 Fuchsia 模擬器執行個體清單,請執行下列指令:

ffx emu list

這個指令會輸出類似以下的輸出內容:

$ ffx emu list
[Inactive]  my-fuchsia-example-01
[Active]    fuchsia-emulator

在輸出結果中,每個模擬器執行個體旁邊都會顯示其狀態。如果狀態為 [Active],表示例項正在執行,並能回應其他 Fuchsia 工具。不過,如果狀態為 [Inactive],則表示執行個體已停止執行,但保留工作目錄,或是執行個體仍在執行,但無法回應 (例如因網路故障)。以停用網路功能啟動的執行個體,即使運作正常,也不會顯示為 [Active]

停止模擬器執行個體

如要停止執行中的 Fuchsia 模擬器例項,請執行下列指令:

ffx emu stop INSTANCE_NAME

INSTANCE_NAME 替換為執行中的 Fuchsia 模擬器執行個體名稱。

下列範例指令會停止 my-fuchsia-example-01 執行個體:

$ ffx emu stop my-fuchsia-example-01

這個指令會輸出類似以下的內容:

$ ffx emu stop my-fuchsia-example-01
Stopping emulator 'my-fuchsia-example-01'...
Terminating running instance 2752927

這個指令會終止該模擬器的執行程序,並移除在主機電腦上為該執行個體建立的臨時工作目錄。(如果您想保留這個工作目錄,請參閱「停止執行中的模擬器執行個體,同時保留工作目錄」一文。

如果只有一個執行中的模擬器執行個體,您可以省略 INSTANCE_NAME 欄位以停止執行個體,例如:

$ ffx emu stop
Stopping emulator 'fuchsia-emulator'...
Terminating running instance 2752927

如要一次停止所有執行中的例項,您可以使用 --all 標記,例如:

$ ffx emu stop --all
Stopping emulator 'my-fuchsia-example-01'...
Stopping emulator 'fuchsia-emulator'...
Terminating running instance 2749406

停止模擬器執行個體,同時保留其工作目錄

停止執行中的模擬器執行個體時,根據預設,該執行個體的工作目錄會從主機中刪除。不過在某些情況下,您可能會想要保留執行個體的工作目錄,以便繼續檢查目錄內容以進行偵錯。

如要在不刪除工作目錄的情況下停止執行中的 Fuchsia 模擬器執行個體,請執行下列指令:

ffx emu stop INSTANCE_NAME --persist

INSTANCE_NAME 替換為執行中的 Fuchsia 模擬器執行個體名稱。

下列範例指令會停止 my-fuchsia-example-01 執行個體:

$ ffx emu stop my-fuchsia-example-01 --persist

這個指令會輸出類似以下的內容:

$ ffx emu stop my-fuchsia-example-01 --persist
Stopping emulator 'my-fuchsia-example-01'...
Terminating running instance 2752927

執行此指令後,執行個體的工作目錄會保留在主機上,而已停止的執行個體會繼續顯示在模擬器執行個體清單 (ffx emu list) 中,並顯示 [Inactive] 狀態。

如要重新啟動這個已停止的模擬器執行個體,請搭配 --reuse 標記執行 ffx emu start 指令,例如:

$ ffx emu start my-fuchsia-example-01 --reuse

當您不再需要工作目錄時,可以再次執行 ffx emu stop 指令來刪除目錄,例如:

$ ffx emu stop my-fuchsia-example-01
Stopping emulator 'my-fuchsia-example-01'...

顯示模擬器設定

如要在主機上查看 Fuchsia 模擬器設定,請執行下列指令:

ffx emu show

這個指令會輸出類似以下的輸出內容:

$ ffx emu show
EmulatorConfiguration {
    device: DeviceConfig {
        audio: AudioDevice {
            model: Hda,
        },
        cpu: VirtualCpu {
            architecture: X64,
            count: 0,
        },
...

在 Tun/Tap 網路模式中啟動 Fuchsia 模擬器

--net tap 模式中,主機機器的核心會設定虛擬網路通道裝置 (請參閱 Tun/Tap),並將裝置與主體機器的實體網路橋接。這項設定可讓透過虛擬裝置傳送的流量,轉送至實體網路。接著,模擬器會將執行個體的虛擬網路介面,連接至主體機器上的虛擬通道裝置。這與模擬器例項直接連線至主機的實體網路相同。因此,--net tap 模式可在所有網路選項中提供最快的效能。不過,這個模式的設定需要主機上有超級使用者存取權 (sudo),且僅支援 Linux 主機。

如要在 Tun/Tap 網路模式下啟動模擬器,請執行下列指令:

ffx emu start PRODUCT_BUNDLE --net tap

PRODUCT_BUNDLE 替換為在您主體機器上下載的產品套件路徑。

以下範例指令使用 ~/local_pb 目錄做為產品套裝組合:

$ ffx emu start ~/local_pb --net tap

這個指令會輸出類似以下的輸出內容:

$ ffx emu start ~/local_pb --net tap
Logging to "/home/alice/.local/share/Fuchsia/ffx/emu/instances/fuchsia-emulator/emulator.log"
Waiting for Fuchsia to start (up to 60 seconds)......................
Emulator is ready.

使用 Tun/Tap 網路模式時,您可以選擇指定「upscript」,例如設定網路介面和防火牆例外狀況。凡是透過 Tun/Tap 網路模式執行的模擬器執行個體,都會在啟動時執行這個指令碼。

如要在 ffx 設定中新增網路 Upscript,請在啟動模擬器前執行下列指令:

ffx config set emu.upscript <PATH_TO_UPSCRIPT>

PATH_TO_UPSCRIPT 替換為 upscript 檔案的路徑。

以下範例指令會將 my-upscript.sh 新增至 ffx 設定:

$ ffx config set emu.upscript /home/alice/my-fuchsia-project/my-upscript.sh

以使用者網路模式啟動 Fuchsia 模擬器

如果您沒有主機機器上的超級使用者存取權 (sudo),則可以使用 --net user 模式設定網路。在這個模式下,模擬器會充當防火牆 (透過 SLiRP)。來自模擬器執行個體的流量沒有限制。不過,傳送流量至模擬器執行個體需要進行以下設定:

  • 虛擬裝置規格是產品套裝組合 (例如 ~/local_pb) 的一部分,會預先定義裝置所需的通訊埠對應。
  • 這些通訊埠可以在啟動模擬器執行個體時,對應至主機上的未使用通訊埠。

舉例來說,如要設定主機與模擬器執行個體之間的 SSH 連線,首先產品套件的虛擬裝置規格必須允許裝置使用執行個體的 SSH 連接埠 (通常為 22)。接著,啟動 Fuchsia 模擬器時,您可以使用 ffx emu start 指令將執行個體的 SSH 通訊埠對應至主機上未使用的通訊埠,例如 8022。接著,等模擬器執行個體開始執行後,您就可以透過主機的通訊埠 8022,建立連至執行個體的 SSH 工作階段。

在虛擬裝置規格中,ports 欄位會提供服務名稱和通訊埠號碼清單,例如:

ports = {
        ssh = 22
        mdns = 5353
        debug = 2345
}

上例表示模擬器必須在啟動期間,將模擬器執行個體的三個指定通訊埠 (即 22、5353 和 2345) 對應至主機上的未使用通訊埠。根據這項規格,模擬器會分別使用名稱 sshmdnsdebug 做為三個通訊埠。針對每個通訊埠,您可以使用 --port-map 標記將名稱對應至主機電腦上未使用的通訊埠,例如:

$ ffx emu start ~/local_pb --net user --port-map ssh:8022 --port-map debug:12345

在虛擬裝置規格中,任何未使用 --port-map 旗標明確對應的通訊埠,都會在啟動期間任意指派給主機機器上未使用的通訊埠。最終的通訊埠對應會顯示在 ffx emu show 的輸出內容中。

如要在使用者網路模式中啟動模擬器,請執行下列指令:

ffx emu start PRODUCT_BUNDLE --net user [--port-map PORT_NAME:PORT_NUMBER]

請更改下列內容:

  • PRODUCT_BUNDLE:在您的主體機器上下載的產品套件路徑。
  • PORT_NAME:(選填) 模擬器執行個體上的服務名稱。
  • PORT_NUMBER:(選用) 您要對應 PORT_NAME 服務目標的主體機器通訊埠編號。

下方的範例指令會在使用者網路模式下啟動模擬器:

$ ffx emu start ~/local_pb --net user

如未指定 --port-map 旗標,模擬器會將模擬器執行個體上的服務對應至主機電腦上任何未使用的通訊埠。

以下範例指令會在使用者網路模式下啟動模擬器時,指定通訊埠對應項目:

$ ffx emu start ~/local_pb --net user --port-map ssh:8022 --port-map debug:12345

如要瞭解使用者網路模式中模擬器執行個體的通訊埠對應方式,請執行 ffx emu show 並檢查輸出內容的 port_map 欄位,例如:

$ ffx emu show
EmulatorConfiguration {
    [...]
    host: HostConfig {
        [...]
        networking: User,
        port_map: {
            "ssh": PortMapping {
                guest: 22,
                host: Some(
                    8022,
                ),
            },
            "mdns": PortMapping {
                guest: 5353,
                host: Some(
                    35801,
                ),
            },
            "debug": PortMapping {
                guest: 2345,
                host: Some(
                    12345,
                ),
            },
        },
    },
    [...]
}

在停用網路的情況下啟動 Fuchsia 模擬器

指定 --net none 時,與虛擬機器上並未安裝網路卡一樣,模擬器執行個體無法存取網路功能。與模擬器執行個體通訊的唯一機制是透過 QEMU 監控器和模擬序列埠

如要啟動網路已停用的模擬器,請執行下列指令:

ffx emu start PRODUCT_BUNDLE --net none [--console]

PRODUCT_BUNDLE 替換為在您主體機器上下載的產品套件路徑。

這個指令會輸出類似以下的內容:

$ ffx emu start ~/local_pb --net none
Logging to "/home/alice/.local/share/Fuchsia/ffx/emu/instances/fuchsia-emulator/emulator.log"
Waiting for Fuchsia to start (up to 60 seconds).............................................................
Emulator did not respond to a health check before timing out.

停用網路時,ffx emu start 指令無法完成執行個體的「健康狀態檢查」,因此執行個體的狀態會是 [Inactive],如預期出現,例如:

$ ffx emu list
[Inactive]    fuchsia-emulator

啟動 Fuchsia 模擬器,並使用主控台進行偵錯

Fuchsia 模擬器提供下列內建主控台,可讓開發人員與模擬器執行個體互動:

這兩個控制台都支援 QEMU 和 AEMU 引擎。

QEMU 監控器

您可以使用 QEMU 監控器,直接向模擬器程序發出指令。其中部分指令可讓您修改模擬裝置、查詢虛擬硬體狀態,以及使用虛擬硬體信號終止模擬器程序。(如要進一步瞭解可用的指令,請參閱 QEMU Monitor 頁面)。

如要啟動連接至 QEMU 監控器的模擬器執行個體,請執行下列指令:

ffx emu start PRODUCT_BUNDLE --monitor

PRODUCT_BUNDLE 替換為主機上下載的產品套裝組合路徑。

以下範例指令使用 ~/local_pb 產品套件:

$ ffx emu start ~/local_pb --monitor

這個指令會輸出類似以下的輸出內容:

$ ffx emu start ~/local_pb --monitor
QEMU 2.12.0 monitor - type 'help' for more information
(qemu)

當您在執行附加 QEMU 監視器的模擬器執行個體時,指令不會立即退出至終端機。而是會將您帶入 QEMU 監控提示

如要退出 QEMU 監控器提示,您可以發出 quit 指令,這也會終止模擬器執行個體,例如:

$ ffx emu start ~/local_pb --monitor
QEMU 2.12.0 monitor - type 'help' for more information
(qemu) quit

WARNING | Write called without a backing file!
$

Fuchsia 模擬的序列埠

如果模擬器執行個體在連結至模擬序列埠時啟動,Fuchsia 平台會將序列埠視為終端機。在啟動程序中,這個終端機會透過通訊埠串流核心記錄,且系統開機後,會顯示 Fuchsia 指令列提示。

如要啟動連結至模擬序列埠的模擬器執行個體,請執行下列指令:

ffx emu start PRODUCT_BUNDLE --console

PRODUCT_BUNDLE 替換為在您主體機器上下載的產品套件路徑。

以下範例指令使用 ~/local_pb 產品套件:

$ ffx emu start ~/local_pb --console

這個指令會輸出類似以下的內容:

alice@alice:~$ ffx emu start ~/local_pb --console
INFO    | Android emulator version 31.3.8.0 (build_id 8611574) (CL:N/A)
[... various log entries]
[00021.699] 01095:01158> [component_manager] INFO: Connecting fuchsia.sys2.LifecycleController
$

啟動模擬器執行個體之後,這個指令會將您帶入 Fuchsia 指令列提示中,方便您將各種裝置端指令列直接發送至執行個體。

如要結束序列埠主控台,您可以發出 dm poweroff 指令,這個指令也會終止模擬器執行個體,例如:

$ dm poweroff
[00258.335] 26935:26939> [shutdown-shim]: checking power_manager liveness
[... various log entries]
[00260.447] 03742:03744> [00260.447038][3742][3744][driver_manager.cm] WARNING: [src/devices/bin/driver_manager/v1/suspend_handler.cc(211)] Failed to cause VFS exit ourselves, this is expected during orderly shutdown: FIDL operation failed d
[00260.429] 03341:03344> WARNING | Write called without a backing file!
alice@alice:~$