アーキテクチャ
トップページで、分割を紹介しました。カーネルがハードウェアを所有し、オーケストレーション層が何をするかを決め、両者は 1 本の検査済み境界で出会う。このページは、その分割を実装でどう引いたかです。境界がどこにあり、何がそこを越え、そこからどんな設計判断が落ちてくるか。
FFI 境界は、実行可能性の判定である
二層のあいだの境界は、バイトコードが通り抜けるゲートというだけのものではありません。そこは、要求が機械の実際の状態に照らして検査される場所です。
これは航空宇宙・自動車の制御ソフトウェアでお馴染みの分割です。上位のコントローラがやりたいことを表明し、その下の層が現実に対する実行可能性を判断して、実行・サチュレート・拒否のいずれかを行います。
Lambda OS では、その判断を下すのが FFI ハンドラです。スクリプトでも VM でもなく、カーネルが登録する C 関数がその場所です。バイトコードが意図で、FFI ハンドラが意図と機構の出会う場所であり、機械の実際の状態を確認する場所です。機械ができない、あるいはしてはならないことを求めるミッションは、それを得られません。飛行制御の安全包絡線が、まさにこのパターンです。ネイティブで、提案してくるミッションの 1 つ下の層にあります。
何が native で、何がバイトコードか
すべてがスクリプトなわけではありません。デッドラインを外せないループは、ネイティブの Zig タスクとして、予測可能で計測可能な最悪コストを持つ言語で書きます。
オーケストレーション層が担うのは、いずれ正しければよい部分です。次のウェイポイントを決める、落ちたワーカーを再起動する、状態を報告する——数マイクロ秒のジッタが無害な領域。デッドラインを絶対に落とせない部分は native で、プリエンプトするタイマがあるので、暴走スクリプトはそれを止められません。
どちらに置くかの規則:遅い答えが失敗になるなら native、遅い答えが単に遅いだけならバイトコードでよい。
BMP — アクター 1 つにコア 1 つ
並行モデルは **BMP(bound multiprocessing)**です。すべての VM タスクは 1 つのコアに固定され、移動しません。
これは必然であり、同時に見返りでもあります。VM のプロセス全体の実行状態はコア毎の 1 セットなので、コア間を移動するタスクにはクロスコアのロックが要る。固定すればそれが消えます。そしてこれは、アクターモデルがもともと望んでいることそのものです。アクターは可変状態を共有せずメッセージだけで通信するので、VM のグローバルはコア毎に 1 セットで済み、ロックが要りません。
結果として、ほとんどロックの無いマルチコアシステムになります。割り込み禁止区間は、いずれも数命令の長さで、本当に共有されるデータ——メールボックス、コンソール、送信リング——を守るものだけです。
単一の信頼ドメイン
すべてのバイトコードは、同じ運用者が信頼経路で配布します。敵対的バイトコードの命令レベル検証器は、設計上ありません。
閉じ込めがあるのは別の理由です。バグを封じ込めるためで、敵対者に対する防御のためではありません。各 VM タスクは、そのアーキが提供する最低の特権で走り、カーネルには 1 つの syscall ゲート経由でのみ到達します。そしてその閉じ込めはアクター毎に引かれます。MMU があればアクター毎のアドレス空間、無ければアクター毎の PMP / MPU 領域。だから障害は、それを起こしたアクターの中に留まります。
ここでの隔離は堅牢性の境界であって、マルチテナントの境界ではありません。想定するのは運用者自身のソフトウェアを走らせる専用機器で、脅威は敵対者でなくバグです。どのターゲットでどこまで効くかは 隔離 のページにあります。
層モデル
Lambda C バイトコード → 意図のみ・ハードウェア隔離 (ring 3 / EL0 / U-mode / 非特権)
│ syscall ゲート (int 0x80 / svc / ecall) + FFI (C ABI)
アーキ非依存カーネル → スケジューラ · ネットワーク · VM ホスト (同一ソース・5 ターゲット)
│ HAL セレクタ (コンパイル時に解決)
アーキ層 → cpu · console · mmu · intc · trap · gdt · nic
責務は 3 つに綺麗に分かれます。バイトコードが何をするかを言い、FFI ハンドラが現在の状態に照らして検証し、カーネルとドライバがハードウェアを所有する。各アーキは、それぞれの入口(x86 は UEFI ブートローダ、riscv64 は OpenSBI、aarch64 は EL1、MCU はベアメタルのファームウェア)を通って共通のエントリポイントに到達し、そこから同一のアーキ非依存コードを走らせます。アーキ横断の層そのものは ポータビリティ にあります。
Lambda シリーズにおける位置づけ
Lambda OS は、それ自体で完結した、ゼロから作った RTOS です。カーネルとその native タスクはどのスクリプトにも依存せず、構成をすべて native にすることもできます。
その特色となる上層が、ハードウェア隔離されたアクターによるオーケストレーション層で、そのアクターは Lambda C のバイトコードで記述されます。Lambda C は Lambda シリーズの組み込みオーケストレーション VM で、ふつうは「ハードウェアを所有し、FFI を登録し、どのバイトコードを走らせるかを決める」小さな C プログラムに組み込まれます。
その小さな C プログラムが、プリエンプティブ・マルチコア・ネットワーク対応の OS へ育ったものが Lambda OS であり、各 Lambda C VM はその中でハードウェア隔離されたアクターになります。カーネルは Lambda C に依存していません。両者は設計上きれいに噛み合う姉妹です。