TL

macOS/XNUカーネルとMach・BSDのハイブリッド構造

macOSやiOSが堅牢さと速さを両立できる理由は、XNUがMachとBSDを1つのアドレス空間に同居させた折衷設計にあります。Machポートの仕組みからI/O Kitまで内側を解き明かします。

応用XNUMachBSDmacOSカーネルI/O Kit最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.XNUは純粋なマイクロカーネルではなく、Mach(IPC・仮想メモリ・スケジューリング)とBSD(POSIX・ネットワーク・VFS)を同一カーネル空間に同居させたハイブリッドである。
  • 2.Machの中核はポートを介したメッセージパッシングで、ポートは権利(send/receive権)で守られた一方向のメッセージキューであり、Mig が生成するスタブでRPCとして使われる。
  • 3.デバイスドライバは I/O Kit という C++ フレームワーク上に書かれ、ドライバ同士をオブジェクトとして接続する I/O Registry がデバイスツリーと電源管理を統括する。

XNUは「2つのカーネルを縫い合わせた」ハイブリッド

macOS・iOS・iPadOS などを支える Apple のカーネルが XNU(X is Not Unix)です。名前に反して中身は2つの系譜の合成で、よく「ハイブリッドカーネル」と呼ばれます。中核は3層から成ります。

  • Mach:CMU 由来のマイクロカーネル。IPC(メッセージパッシング)・仮想メモリ・タスク/スレッドとスケジューリングという最下層の機構を担う。
  • BSD(FreeBSD 由来):POSIX API・プロセスモデル・シグナル・ネットワークスタック・VFS(ファイルシステム抽象)・ソケットを提供する上位層。
  • I/O Kit:C++ で書かれたデバイスドライバフレームワーク。

ここで誤解しやすいのは「Mach ベース=マイクロカーネル」という連想です。本来のマイクロカーネルはドライバや FS をユーザー空間のサーバーへ追い出し、IPC で繋ぎます。しかし XNU は性能のため BSD もドライバも Mach と同じカーネル空間に同居させ、内部では IPC ではなく直接の関数呼び出しで連携する。だから純粋なマイクロカーネルではなく、設計上の位置づけは マイクロカーネルとモノリシックの比較 でいうハイブリッドです。Mach のメッセージパッシングのコストを、境界越えを減らすことで回避しているわけです。

なぜ2つを縫い合わせたのか

歴史的経緯です。NeXTSTEP が Mach 2.5 に BSD を載せた構成を採り、それが Apple に買収されて Mac OS X の基盤になりました。Mach だけでは POSIX 互換の豊富な API が揃わず、BSD だけでは Mach の柔軟な VM・IPC・タスク抽象が得られない。両方の資産を捨てずに使うための現実的な折衷が XNU です。

Mach の中核:タスク・スレッド・ポート

Mach の世界では実行とリソースの単位が BSD と別建てです。**タスク(task)**がアドレス空間とリソースの容れ物、**スレッド(thread)**が実際の実行単位で、CPU にスケジュールされるのはスレッドです。BSD の proc(プロセス)は内部的に Mach の task と対応づけられ、1つの実体を2つの顔(BSD の PID と Mach の task port)から見る格好になります。

Mach のあらゆる機能はポート(port)を通じて操作されます。ポートとは、カーネルが管理する一方向のメッセージキューです。重要なのは、ポートが権利(port right)で保護されていることです。

ポート権利意味性質
receive権そのポートからメッセージを取り出せる原則1つのタスクだけが保持(受信者は一意)
send権そのポートへメッセージを送れる複数タスクが保持可能、譲渡・複製できる
send-once権一度だけ送れる使い捨ての送信権返信用ポートなどに使う

タスクが扱うのは生のポインタではなく、自タスク内でのみ有効な port name(整数のハンドル。file descriptor に似た添字)です。カーネルがその name を本物のポート構造体へ翻訳します。だからポート権利はケーパビリティとして働き、send 権を持たないタスクはそのポートへ手出しできません。これが Mach のセキュリティと隔離の土台です。タスク自身を表す task portmach_task_self())の send 権を奪われることは、そのタスクの完全な乗っ取りに等しく、それゆえ厳重に守られます。

Mach メッセージと Mig:IPC を RPC に見せる

Mach IPC の生 API は mach_msg() ただ1つで、送信・受信・その往復(RPC 的な送って待つ)を1コールでこなします。メッセージは固定ヘッダ+本体(データやポート権利の並び)です。本体には2種類のデータが載ります。

mach_msg():
  ヘッダ { 宛先ポート, 返信ポート, サイズ, メッセージID }
  本体   ├─ inline データ(小さい値はメッセージにそのままコピー)
         └─ out-of-line データ / ポート権利
              └ 大きなデータは VM のページマッピングで「移送」
                (物理コピーせず受信側アドレス空間へ写す)

ポイントは、メッセージにポート権利そのものを載せて渡せることです。送信側が「返信はこのポートへ」と返信ポートの send-once 権を同梱すれば、受信側はそこへ結果を返せる。これでリクエスト/レスポンス型の RPC が成立します。大きなデータは物理コピーを避け、仮想メモリ の機構でページを受信側にコピーオンライト的にマッピングして渡します。Mach IPC と VM が深く結合しているのはこのためです。

ただし mach_msg を手で組み立てるのは煩雑なので、実際には Mig(Mach Interface Generator)を使います。Mig は IDL(インターフェース定義)からクライアント側スタブとサーバー側スケルトンを生成し、関数呼び出しを自動でメッセージへ整列化(マーシャリング)します。呼ぶ側は普通の関数を呼んでいるように見えて、裏で mach_msg が走り、別タスク(しばしばカーネル自身)で処理される——構造としては プロセス間通信(IPC) の上に RPC を被せたものです。host_infotask_for_pid といった Mach の各種サービスはこの形で呼ばれます。

Mach IPC が VM と一体である理由

out-of-line データの「移送」は、ページテーブルの操作だけで完結します。送信側のページを受信側アドレス空間へマップし、書き込みが起きるまで実体を共有する(コピーオンライト)。巨大なメッセージでもメモリ帯域を食わずに渡せるのは、Mach の IPC がメッセージング機構でありながら同時に VM 機構でもあるからです。L4 がレジスタ渡しで小メッセージを速くしたのに対し、Mach は大メッセージをページ移送で軽くする方向に最適化しています。

BSD 層:POSIX の顔とネットワーク・VFS

ユーザー空間のアプリが触れる「Unix らしさ」はほぼ BSD 層が担います。fork/exec/wait、シグナル、pthreadsocket、ファイル I/O、そして VFS によるファイルシステム抽象——これらは FreeBSD 由来のコードがカーネル内で提供します。だから macOS では、同じカーネル機能を2つの API レイヤから呼べます。

観点Mach 層BSD 層
実行単位task / threadprocess(proc)/ pthread
識別子port name(ハンドル)PID / file descriptor
主な責務IPC・VM・スケジューリングPOSIX API・NW・VFS・シグナル
呼び出し様式mach_msg によるメッセージ従来型のシステムコール(trap)

両者はシステムコールの番号空間でも区別されます。XNU では、システムコール番号が正なら BSD(Unix)系、負なら Mach トラップとして振り分けられます。openread は前者、mach_msg_trap などは後者です。BSD のプロセス管理は内部で必ず対応する Mach task/thread を操作するので、fork 一つとっても「BSD が proc を作り、Mach が task とアドレス空間を用意する」という二層の協調になります。スレッドが CPU を得るかどうかを最終的に決めるのは Mach のスケジューラで、BSD はその上に POSIX 的な見え方を被せているにすぎません。

2系統あることの落とし穴

同じ実体に2つの ID 体系があるため、PID と task port の対応づけ(task_for_pid)は強い権限です。任意プロセスの task port を取れれば、そのアドレス空間の読み書きや実行制御ができてしまう——デバッガが可能なのもこれが理由です。だから近年の macOS では SIP(System Integrity Protection)や署名・エンタイトルメントで task_for_pid を厳しく制限し、他プロセスへの侵入経路を塞いでいます。

I/O Kit:オブジェクト指向のドライバ機構

XNU のデバイスドライバは、Mach でも BSD でもなく I/O Kit という独立フレームワーク上に書かれます。言語は Embedded C++(例外・多重継承・RTTI などを外した C++ サブセット)で、ドライバをクラスのインスタンスとして表現するのが特徴です。Linux の デバイスドライバモデル が構造体とコールバックで組むのに対し、I/O Kit はクラス継承とオブジェクト接続でドライバを構築します。

中核概念は次の通りです。

  • IOService:すべてのドライバ/デバイスの基底クラス。probestartstop というライフサイクルを持つ。
  • マッチング:新しいデバイスが現れると、I/O Kit はそのプロパティ(ベンダID等)にマッチする driver クラスの候補を探し、probe でスコアを競わせ、最良のものを start する。
  • I/O Registry:起動中の IOService インスタンスを生きたツリーとして保持する動的データベース。デバイス間の親子(provider/client)関係がここに記録され、ioreg コマンドで覗ける。
  • 電源管理:provider/client のツリーをたどって、依存するデバイスの電源状態を整合的に上げ下げする。
I/O Registry(抜粋イメージ):
  IOPCIDevice (GPU)
    └─ provider/client 関係でぶら下がる
         IOFramebuffer ──> ディスプレイ
  IOUSBHostDevice
    └─ IOUSBInterface ──> HID ドライバ

I/O Registry が「マッチング済みのドライバの接続グラフ」を保持するからこそ、ホットプラグでデバイスが現れた瞬間に候補ドライバが start され、抜ければ stop されて木から外れる、という動的な追従が成立します。ドライバ間の依存(あるドライバが下位ドライバを provider として要求する)もこのツリー上の関係として表現され、電源やリソースの整合性が保たれます。

試験・面接での要点整理

押さえどころは4つ。(1) XNU は Mach+BSD+I/O Kit のハイブリッドで、純粋マイクロカーネルではなく内部は関数呼び出しで連携する。(2) Mach の IPC はポート(receive 権を持つ受信者は一意、send 権は複製可能なケーパビリティ)へのメッセージパッシングで、mach_msg 1コールに集約され、Mig がそれを RPC に見せる。(3) 大データは VM のページ移送(COW)で渡され、IPC と VM が一体。(4) ドライバは I/O Kit の C++ オブジェクトで、I/O Registry がデバイスツリーと電源管理を統括する。

まとめ

まとめ

XNU はMach(IPC・VM・スケジューリング)・BSD(POSIX・NW・VFS)・I/O Kit(ドライバ)を同一カーネル空間に同居させたハイブリッドです。Mach は本来マイクロカーネルですが、XNU は性能のため境界越えを IPC ではなく関数呼び出しに置き換えて取り込みました。Mach の中核はポートを介したメッセージパッシングで、ポートは send/receive 権というケーパビリティで守られ、mach_msg に集約された IPC を Mig が RPC として見せます。大きなメッセージは VM のページ移送で軽く渡され、IPC と VM が一体である点が Mach らしさです。一方の BSD 層は同じ実体に PID/fd という Unix の顔を与え、ドライバは I/O Kit のオブジェクトとして I/O Registry のツリー上で接続・電源管理されます。2つの系譜を縫い合わせた折衷こそが、堅牢さと豊富な POSIX 互換、そして高い性能を両立させる XNU の正体です。

設計の位置づけは マイクロカーネルとモノリシックの比較、通信の基礎は プロセス間通信(IPC)、ドライバ機構の対比は デバイスドライバモデル も合わせてどうぞ。

OS Article

macOS/XNUカーネルとMach・BSDのハイブリッド構造を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

XNU

比較で見る軸

難易度: advanced / カテゴリ: OS / タグ数: 6

導入後に効く点

Machの中核はポートを介したメッセージパッシングで、ポートは権利(send/receive権)で守られた一方向のメッセージキューであり、Mig が生成するスタブでRPCとして使われる。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
OS
タグ数
6

判断チェックリスト

  • 自社の用途が「XNU / Mach」に近いか確認する。
  • 強みである「XNUは純粋なマイクロカーネルではなく、Mach(IPC・仮想メモリ・スケジューリング)とBSD(POSIX・ネットワーク・VFS)を同一カーネル空間に同居させたハイブリッドである。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

XNUMachBSDmacOSカーネルXNUMachBSD
参考: 公式情報