啟動 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-emulator 的 Fuchsia 模擬器。不過,如要以不同名稱啟動 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]

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

$ 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/輕觸網路模式中啟動 Fuchsia 模擬器

--net tap 模式中,主機機器的核心會設定虛擬網路通道裝置 (請參閱「Tun/Tap」),並將該裝置與主機機器的實體網路相互連結。這項設定可讓來自虛擬裝置的流量轉送至實體網路。然後再將執行個體的虛擬網路介面附加至主體機器上的虛擬通道裝置。這效果與模擬器執行個體直接連線至主體機器的實體網路相同。因此,--net tap 模式在所有網路選項中提供了最快的效能。不過,此模式的設定需要有主機機器的超級使用者存取權 (sudo),並且僅支援 Linux 主機 (但也有開放原始碼擴充功能可以在 macOS 主機上啟用這項設定)。

如要在 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/輕觸網路模式,您可以選擇指定「upscript」(向上指令碼),例如設定網路介面和防火牆例外狀況。只要是使用 Tun/Tap 網路模式執行的模擬器執行個體,就會在啟動時執行這個指令碼。

如要在 ffx 設定中新增 Network upscript,請先執行下列指令再啟動模擬器:

ffx config set emu.upscript <PATH_TO_UPSCRIPT>

PATH_TO_UPSCRIPT 替換為上標檔案的路徑。

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

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

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

如果您沒有主機機器上的超級使用者存取權 (sudo),或不想將 macOS 設定調整為使用 Tun/Tap (請參閱 --net tap 模式),則可使用 --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 監控器頁面)。

如要啟動連接至 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:~$