Google Fuchsiaについて調べてみた

本記事は 自作OS Advent Calendar の14日目の記事となります(狙ったわけではないですが偶然にも昨年と同じ14日目の登場となりました)。

adventar.org

みなさま、ご無沙汰しております。

自作OSに復帰する みたいなことを去年のAdvent Calendarに書いたものの、今年は昨年と同様かそれ以上に忙しくなかなかOS自作に取り組む時間を捻出できませんでした。。

まずは自作OSもくもく会に復帰したいなと思いつつ、今年のAdvent CalendarもOS自作と関係ないようで関係ありそうなトピックにしました。

今回のテーマは Google Fuchsia です。今回は、この謎の多いGoogleの新OSについて色々と調べてみました。

余談ですが、GIZMODOの記事によれば、Fuchsiaフューシャ と読むみたいですが、Google翻訳でFuchsiaの記事を翻訳すると フクシア と出ますね。

目次

Google Fuchsiaの概要

Google Fuchsiaとは

Google Fuchsia(以下 Fuchsia と略して記載します)は2016年8月に何の前触れもなく突然現れました。

※当時の記事

gihyo.jp

登場から2年以上経過していますが、当時と状況はあまり変わっておらず、2016年から今に至るまで、公式に発表されているプロダクトではありません(私の方でも改めて調べてみましたが、Googleからの公式発表は結局見つからず)。公式の情報源はGoogleのFuchsiaリポジトリにあるドキュメント群と下記Githubリポジトリ(リポジトリ名にmirrorと入っているのでGoogleのFuchsiaリポジトリのミラーと思われます)しかない、未だ謎の多きプロジェクトです。

github.com

余談ですが、Fuchsiaのロゴって富士通のロゴの鏡写しみたいなデザインですね。

Google Fuchsiaの特徴

公式発表すらされていないFuchsiaですが、公式リポジトリのドキュメントや各種紹介記事やプレゼン資料を総合すると、下記のような特徴をもったOSです。

  1. マイクロカーネルである (Linuxモノリシックカーネル)
  2. 全くの新規で開発されている (AndroidLinuxカーネルの上に各種フレームワークを構築しているのに対して、Fuchsiaは新規開発のカーネルを使用している)
  3. POSIX互換のシステムコールインタフェース *1
  4. C++ベースで実装されている

ところで、Fuchsiaは私自身の感覚としてはOS開発というよりはモバイルアプリケーション開発の文脈で話が出ることが割と多い気がしています。とりわけAndroidからFuchsiaへ置き換えるといった噂は盛んに報じられています。下記の記事もそういった噂を報じた記事の1つです。

gigazine.net

それは、ひとえにFuchsiaのGUIアプリケーション開発にFlutterというモバイルアプリ開発で最近話題のフレームワークを使えることが主な理由なのではないかと思います。

Google Fuchsiaのアーキテクチャ

The Fuchsia layer cake

公式ドキュメントによれば、Fuchsiaは下記4つのレイヤ(The Fuchsia layer cake)から構成されています。

  • Zircon
    • レイヤーの最下層に位置する、Fuchsiaのカーネル
  • Garnet
    • ネットワーク、メディア、グラフィックスサービスなどのシステムサービスが属するレイヤー
  • Peridot
    • アプリケーションの実行に関連したフレームワーク(のようなもの?) *2 *3
      • 各アプリケーションのライフサイクルやViewの階層の管理を担う
    • Googleアカウントの同期や他デバイスとの同期基盤もPeridotが提供
    • 解説記事などを読んでも一番理解し辛い(と感じた)層
  • Topaz
    • レイヤーの最上層に位置する
    • UIやシェルを提供する

Zirconカーネルについて

Zircon はFuchsiaのカーネルです。昔は Magenta と呼ばれていました。

Zirconはマイクロカーネルで、システムコールの他に、スレッド、ソケット、仮想メモリマネージャ、割り込みなどの標準的なカーネルの機能を提供します。 *4 *5 ただし、ファイルシステムカーネルには含まれず、またユーザ空間で実行されます。ファイルシステムの扱いについてはLinuxなどはカーネル空間でファイルシステムを扱っており、この点はZirconの大きな特徴といえるのではないでしょうか。

Zircon Kernel Concepts によれば、カーネルの各種機能はカーネルオブジェクトとして実装されています(ドキュメントでもZircon is a object-based kernel.と記載されているほどで、Zirconの大きな特徴です)。ユーザ空間のプログラムは、システムコールを介してこれらのカーネルオブジェクトにアクセスすることができます。

Zirconのシステムコールlibzircon.so によって提供されます。libzircon.so は vDSO と呼ばれています。また、Zirconのシステムコールは非POSIX互換です。 *6

ファイルシステム

Filesystem Architectureによれば、Fuchsiaのファイルシステムはユーザ空間内に存在します。これにより、Fuchsiaではカーネルの再コンパイル無しにファイルシステムを柔軟に変更することができます。

Fuchsiaでのファイルシステムにあたるものはファイルシステムサービスとなっており、クライアントアプリはこのファイルシステムサービスに処理の要求を出すことによってファイルの読み書きを実現します。

また、Fuchsiaのファイルシステムでは Namespace と呼ばれるクライアントごとのファイルシステムを持ちます。クライアントは任意のルート(ディレクトリハンドル)を設定することになります。そのため、Linuxのようなグローバルのルートファイルシステムは持たず、クライアントごとにアクセス範囲を制限することができます。

別なNamespaceへアクセスしたい場合には、別なNamespaceの特定のディレクトリへのマッピングという形でアクセスことになります。 *7

Google Fuchsiaのビルドと実行

※ 本項の内容は公式リポジトリgetting_started.md、および下記記事とほぼ同じ内容になります(一部元記事にないところで詰まった箇所があったので、そこだけは役に立つかもしれません)。

qiita.com

本当なら、ちょっとしたGUIアプリでも作ってみようかと思ったのですが、残念ながらそこまで到達できませんでした。。ただ、OSの実行まではできたので、macOSでFuchsiaをビルドして動かす方法について紹介します。

なお、ここでの解説内容は公式リポジトリにあるソースのビルド方法となります。公式リポジトリのビルド方法とGithubにあるミラーリポジトリのビルド方法は少し異なるのでご注意ください。

ビルドに必要なツールのインストール

Xcodeインストール済みの人は無視してください。

macOSの場合はコマンドラインツールをインストールしてください。下記コマンドでインストールすることができます。

xcode-select --install

プロジェクト一式のダウンロード

それでは、ソースコードとツール一式が含まれたプロジェクトをダウンロードしましょう。ただし、ソースコードのダウンロード方法が少し特殊です。下記コマンドを実行してダウンロードしてください。

curl -s "https://fuchsia.googlesource.com/scripts/+/master/bootstrap?format=TEXT" | base64 --decode | bash

fxのセットアップ

ビルドやFuchsiaの起動には fx というツールを使います。fxが使えるようシェル周りを設定していきましょう。まず、ダウンロードしてできた fuchsia というディレクトリのルートに .jiri_root という名前のディレクトリがあるので、これを ~/ へコピーしましょう。

cd fuchsia
cp -r .jiri_root ~/

コピーできたら、 .jiri_root/bin/ の中にfxがあるので、PATHを設定しましょう。

私は今年からfish shellを使っているのですが、fish shellの場合は ~/.config/fish/config.fish に下記1行を追加してください。

set -x PATH $HOME/.jiri_root/bin $PATH

bashをお使いの方は .bashrcに下記を追加します。

export PATH="$HOME/.jiri_root/bin:$PATH"

zircon/prebuilt/prebuilt/downloadの内容をダウンロードする ※必要に応じて

ひょっとするとこの手順は環境によっては必要ないかもしれませんが、私の環境ではzirconのビルド時に zircon/prebuilt/download が無いためにビルドエラーが発生しました。

私の環境の場合は zircon/scripts/download-prebuilt を実行することでビルドに必要なバイナリをダウンロードすることができました。コマンドとしては下記のとおりに実行します。

 ./zircon/scripts/download-prebuilt

Fuchsiaのビルド

ビルドをはじめる前に、ターゲットのCPUアーキテクチャを設定します。

Fuchsiaが現在サポートしているCPUは x64 arm64 です。ここではターゲットを x64 として解説します。

ターゲットの設定は下記コマンドで行います。

fx set x64

なお、上記コマンドだとデバッグビルドになります。リリースビルドにしたい方は下記コマンドを実行してください。

fx set x64 --release

ここまでできたら、あとは実際にビルドを実行するだけです。下記コマンドでビルドを開始しましょう。

fx full-build

ビルドに使うマシンによりますが、結構な時間がかかりますので気長に待ちましょう。

Fuchsiaの起動

ダウンロードしたプロジェクト一式の中にQEMUが既に含まれており、下記コマンド1つでビルドしたFuchsiaを実行できてしまいます(とてつもなく楽です)。

fx run

なお、GUIを有効にした状態で起動する際には -g オプションを付加して起動します。

fx run -g

ただし、起動すればわかるとおり、カッコいいUIが出てくるわけではなく、下記のようにコマンドラインしか表示されません。

f:id:kotetuk:20181211220811p:plain:w320
実行時の画面

実は、FuchsiaのGUIVulkan というグラフィックスAPIのサポートが必須なのですが、残念ながらQEMUの方がVulkan未サポートなので、カッコいいUIにはお目にかかれなさそうです。。

余談ですが、Pixelbookで起動した猛者がいて、その際の画面の様子を見たい方は下記動画を見てみると、実際のGUIのイメージがつかめると思います。

www.youtube.com

dmコマンド

Fuchsiaのシェルでは lspwd などのLinuxなどで使えるコマンドも普通に使えます。

ただ、Fuchsiaのシャットダウンや各種デバッグ、デバイス情報を確認したい場合は dm コマンドを使います。

$ dm help
dump              - dump device tree
poweroff          - power off the system
shutdown          - power off the system
suspend           - suspend the system to RAM
reboot            - reboot the system
reboot-bootloader - reboot the system into bootloader
reboot-recovery   - reboot the system into recovery
kerneldebug       - send a command to the kernel
ktraceoff         - stop kernel tracing
ktraceon          - start kernel tracing
devprops          - dump published devices and their binding properties
drivers           - list discovered drivers and their properties

Fuchsiaをシャットダウンしたい場合は shutdown または poweroff オプションを使います。

dm shutdown

また、 dump オプションを使うと、デバイストレースを確認することができます。Fuchsiaの構成が垣間見えるようでおもしろかったので、付録2として実行結果を掲載しておきます。

まとめ

公式発表されていないために情報源が少なく、調査に苦労しましたが、自作OSを嗜む者として、Fuchsiaは面白そうな題材だなという感想を改めて持ちました。

また、LinuxUNIX系の多くのOSはC言語で実装されたモノリシックカーネルであるのに対し、FuchsiaはC++で実装されたマイクロカーネルであることも、コードが読めるOSの実装例として、とても貴重だと思います。

各種ドキュメントやソースコードの解読が進んで、多くの知見が自作OS界隈にもたらされると良いなと思いつつ、私も時間を見つけて解読を進めたいなと思いました。

付録1:Fuchsiaの情報源

付録2:dm dumpの実行結果

※ コマンド実行結果の見方については Zircon Device Modelに記載されています。

$ dm dump
[root]
   <root> pid=2058 
      [null] pid=2058 /boot/driver/builtin.so
      [zero] pid=2058 /boot/driver/builtin.so
   [misc]
      <misc> pid=2126 
         [console] pid=2126 /boot/driver/console.so
         [demo-fifo] pid=2126 /boot/driver/demo-fifo.so
         [dmctl] pid=2126 /boot/driver/dmctl.so
         [tapctl] pid=2126 /boot/driver/ethertap.so
         [hidctl] pid=2126 /boot/driver/hidctl.so
         [ktrace] pid=2126 /boot/driver/ktrace.so
         [ptmx] pid=2126 /boot/driver/pty.so
         [nand-ctl] pid=2126 /boot/driver/ram-nand.so
         [ramctl] pid=2126 /boot/driver/ramdisk.so
         [sysinfo] pid=2126 /boot/driver/sysinfo.so
   [sys]
      <sys> pid=1990 /boot/driver/bus-acpi.so
         [cpu-trace] pid=1990 /boot/driver/bus-acpi.so
         [acpi] pid=1990 /boot/driver/bus-acpi.so
            [acpi-pwrbtn] pid=1990 /boot/driver/bus-acpi.so
               [hid-device-000] pid=1990 /boot/driver/hid.so
            [rtc] pid=1990 /boot/driver/bus-acpi.so
               [rtc] pid=1990 /boot/driver/intel-rtc.so
            [i8042] pid=1990 /boot/driver/bus-acpi.so
               [i8042-keyboard] pid=1990 /boot/driver/pc-ps2.so
                  [hid-device-001] pid=1990 /boot/driver/hid.so
               [i8042-mouse] pid=1990 /boot/driver/pc-ps2.so
                  [hid-device-002] pid=1990 /boot/driver/hid.so
         [pci] pid=1990 /boot/driver/bus-acpi.so
            [00:00.0] pid=1990 /boot/driver/bus-pci.so
            [00:01.0] pid=1990 /boot/driver/bus-pci.so
               <00:01.0> pid=2531 /boot/driver/bus-pci.proxy.so
                  [bochs_vbe] pid=2531 /boot/driver/simple.bochs.so
                     [display-controller] pid=2531 /boot/driver/display.so
            [00:02.0] pid=1990 /boot/driver/bus-pci.so
               <00:02.0> pid=2581 /boot/driver/bus-pci.proxy.so
                  [ahci] pid=2581 /boot/driver/ahci.so
                     [sata0] pid=2581 /boot/driver/ahci.so
                        [block] pid=2581 /boot/driver/block.so
                           [fvm] pid=2581 /boot/driver/fvm.so
                              [blobfs-p-1] pid=2581 /boot/driver/fvm.so
                                 [block] pid=2581 /boot/driver/block.so
                              [minfs-p-2] pid=2581 /boot/driver/fvm.so
                                 [block] pid=2581 /boot/driver/block.so
            [00:1f.0] pid=1990 /boot/driver/bus-pci.so
            [00:1f.2] pid=1990 /boot/driver/bus-pci.so
               <00:1f.2> pid=2657 /boot/driver/bus-pci.proxy.so
                  [ahci] pid=2657 /boot/driver/ahci.so
            [00:1f.3] pid=1990 /boot/driver/bus-pci.so
   [test]
      <test> pid=2023 
         [test] pid=2023 /boot/driver/test.so
         [wlantapctl] pid=2023 /system/driver/wlantap.so