啟動 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 模式。

列出所有可用的產品組合

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

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] 狀態。

如要重新啟動已停止的模擬器執行個體,請執行 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/Tap 網路模式啟動 Fuchsia 模擬器

--net tap 模式中,主機的 Kernel 會設定虛擬網路通道裝置 (請參閱「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 設定,請在啟動模擬器前執行下列指令:

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

這個指令會輸出類似以下的結果:

$ 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 指令列提示,您可以在其中直接對執行個體發出各種裝置端指令列。

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

$ power off
[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!
$

啟動 Fuchsia 模擬器,支援 UEFI 和 GPT 磁碟映像檔

Fuchsia 模擬器會從平面磁碟映像檔啟動已啟用 UEFI 的執行個體,因此可支援實體裝置的近似值。這個映像檔包含 GPT 分區表和傳統的 Fuchsia ABR (系統分區 A、B復原分區) 分區配置。系統分割區支援加密的 ZBI,且可透過 fx ota 進行 OTA 更新,以端對端驗證系統更新程序。請注意,這項功能僅適用於在 Fuchsia 來源結帳時

如要以這個模式啟動模擬器,必須提供 --uefi 標記,以及 ZBI 加密的金鑰和金鑰中繼資料。如要進行測試,Fuchsia 原始碼樹狀結構包含適用的金鑰。假設目前目錄是 Fuchsia 來源簽出作業的根目錄,即可透過這種方式啟動模擬器:

$ ffx emu start --uefi \
  --vbmeta-key third_party/android/platform/external/avb/test/data/testkey_atx_psk.pem \
  --vbmeta-key-metadata third_party/android/platform/external/avb/test/data/atx_metadata.bin
[emulator] defaulting to qemu engine to support uefi.
Use `--engine` to explicitly set the engine type if needed.
Logging to "/path/to/home/dir/.local/share/Fuchsia/ffx/emu/instances/fuchsia-5254-475e-82ef/emulator.log"
Waiting for Fuchsia to start (up to 60 seconds).....
Emulator is ready.
$

將金鑰和中繼資料設為設定選項

如要簡化工作流程,可以避免每次在指令列上傳遞 --vbmeta-key--vbmeta-key-metadata 引數。如要設定這些值,可以透過 ffx config,例如:

$ ffx config set emu.vbmeta.key $(fx get-src-dir)/third_party/android/platform/external/avb/test/data/testkey_atx_psk.pem
$ ffx config set emu.vbmeta.metadata $(fx get-src-dir)/third_party/android/platform/external/avb/test/data/atx_metadata.bin