カーネル
マイクロカーネルとは、伝統的な「カーネル」から「サーバ」群に機能を移転するOS設計方針を意味し、最小化したカーネルだけをカーネル空間に残し、サーバ群を可能な限りユーザ空間で動作させる。マイクロカーネルでは、ハードウェアの単純な抽象化と最小のプリミティブ(システムコール)で最小のOSサービスを実装する(メモリ管理、マルチタスク、プロセス間通信など)。他の全てのサービス(ネットワークなど)は「サーバ」としてユーザ空間に実装される。マイクロカーネルはモノリシックカーネルよりも保守が容易だが、システムコール回数やコンテキストスイッチ回数が増大するために性能が低下する傾向がある。
どうしても特権モードでなければならない部分だけがカーネル空間に置かれる。それは、IPC(プロセス間通信)、基本スケジューラ(スケジューリング・プリミティブ)、基本メモリハンドラ、基本I/Oプリミティブなどである。スケジューラ本体やメモリ管理、ファイルシステム、ネットワークスタックといった大部分はユーザ空間で動作する。マイクロカーネルは、システム機能全体がプロセッサのシステムモードで動作する1つのプログラムになっているモノリシックカーネルの設計方針への反発から生まれた。マイクロカーネルを採用したOSとしては、QNXや GNU Hurd がある。マイクロカーネルは基本的に次のような長所を持つ。
保守は相対的に容易である。
パッチの評価が容易である。
すばやく開発でき、多くの場合カーネルを再起動しなくとも評価可能。
サーバで障害が発生しても、運用上のミラーで代行可能なことが多く、バグへの耐性が高い。
多くのマイクロカーネルは、何らかのメッセージパッシングシステムを採用しており、サーバからサーバへの要求の転送を行う。一般にマイクロカーネルがそのためのポートを用意している。例えばメモリ追加要求を送ると、マイクロカーネルのあるポートが開き、そこを通して要求が転送される。マイクロカーネルにメッセージが受信されると、その後はシステムコールのように処理される。これによってシステムアーキテクチャのモジュール性が高まり、システムがより整理され、デバッグや動的変更が容易になり、ユーザーのニーズに従ったカスタマイズが可能となる。AIX、BeOS、Hurd、macOS、MINIX、QNX といったOSは多かれ少なかれマイクロカーネルの設計方針を取り入れている。マイクロカーネル自体は非常に小さいが、システム機能全体を構成するコードを全て集めると、モノリシックカーネルよりも大きいことが多い。モノリシックカーネル支持派はまた、マイクロカーネル方式の2層構造によりOSの大部分がハードウェアと直接相互作用できなくなるため、決して小さくないコストが上乗せされ、システムの効率を低下させると主張している。マイクロカーネルは通常、アドレス空間定義部、プロセス間通信 (IPC)、プロセス管理といった最小限のサービスだけを提供する。ハードウェア処理といった他の機能はマイクロカーネルで直接扱うことはない。マイクロカーネル支持派は、モノリシックカーネルでのエラー(バグ)がシステム全体のクラッシュを引き起こすという欠点を指摘する。しかしマイクロカーネルでは、サーバがクラッシュしてもそのサービスを再起動することでシステム全体のクラッシュを防ぐ可能性がある。しかし、現にLinuxなどのモノリシックカーネルは年単位で安定動作している実績があり、このようなマイクロカーネルの利点がどれほど重要かは疑わしい。
ネットワーキングなどのカーネルサービスは「サーバ」と呼ばれるユーザ空間のプログラムとして実装される。サーバを停止・再起動するだけでOSを更新可能である。例えばネットワークをサポートしていないマシンで、ネットワークサーバは起動する必要がない。サーバ群やカーネルの間でデータをやり取りする作業があるため、モノリシックカーネルにはないオーバヘッドが生じ、効率が低下する。
マイクロカーネルの短所は例えば次のようなものがある。
全体としてメモリをより多く使用する。
インタフェースを持つソフトウェアの数が多く、性能低下の可能性がある。
サーバ群とカーネル間のメッセージングにバグがあると、検出が困難である。
プロセス管理は一般に非常に複雑になりうる。
使用状況によってはマイクロカーネルは不利になる。単一用途のシステムでは動作するプロセス数が小さいため、マイクロカーネルがよく機能し、プロセス管理の複雑さもあまり問題にならない。
マイクロカーネル方式では、OSの他の部分を通常のアプリケーションのように高水準言語で書くことができ、同一のカーネル上で異なるOS(のインタフェース)を使用することもできる。また動的にOSを切り換えたり、複数のOSを同時に使用することもできる。
カーネルが巨大化するにつれて、様々な問題が明らかになってきた。最も明らかな問題はカーネルの大きさ(メモリ使用量)の増大である。これは仮想記憶をカーネル空間にも適用することである程度まで和らげられるが、全てのコンピュータ・アーキテクチャが仮想記憶をサポートできるわけではない。カーネルのサイズを削減するため、不要なコードを削除するなどの改善が必要となるが、これはカーネルの各モジュール間の明らかにされていない依存関係があるために非常に困難である。
マイクロカーネルと比較したときのモノリシックカーネルの様々な欠点から、1990年代の初期までにモノリシックカーネルは時代遅れと考えられるに至った。結果としてLinuxがモノリシックカーネルを採用したことでリーナス・トーバルズとアンドリュー・タネンバウムの間で有名な論争が発生した(アンドリュー・タネンバウムとリーナス・トーバルズの議論)。この議論では、両者の言い分にそれぞれメリットがある。
モノリシックカーネルは設計が容易で、マイクロカーネルよりも迅速に成長することが期待できる。しかし、モノリシックカーネル内のバグは一般にシステムクラッシュを引き起こすのに対して、マイクロカーネルでは一部のサーバに問題が限定される。モノリシックカーネルの支持者は、不正なコードがカーネルに無ければマイクロカーネルの利点はほとんどないと論じる。どちらの側にも成功例がある。マイクロカーネルはロボットや医療用システムで使われており、各コンポーネントが別々の保護されたメモリ空間で動作する。これは最新のモジュールロード方式であってもモノリシックカーネルには不可能であろう。モノリシックカーネルは共有型カーネルメモリを使用するよう最適化されていて、マイクロカーネルのような低速なメッセージ渡しとは異なる。
モノリシックカーネルはコード全体を同じアドレス空間(カーネル空間)に置くよう設計されており、一部の開発者はシステム性能向上に必須の特徴だとしている。一部の開発者はうまく書けばモノリシックカーネルは極めて高効率になるとしている。
1980年代から1990年代初めにかけてのマイクロカーネルの性能は低かった。そういった初期のマイクロカーネルの性能を実測する研究が行われたが、性能が低い原因を深く分析することはなかった。そういったデータが一人歩きし、カーネルモードとユーザモードの切り替え回数が増え、プロセス間通信の回数が増え、コンテキストスイッチの回数が増えたためだ とみなされた。
そして1995年、マイクロカーネルの性能が低い原因として以下のことが推測されている。
マイクロカーネル「方式」全体が実際には非効率
マイクロカーネルで実装された「コンセプト」が非効率
それらコンセプトの特定の「実装」が非効率
この時点でマイクロカーネルを効率化する方法はまだ研究途上であり、正しい技法の構築が求められていた。
一方でモノリシックカーネルの設計の基盤となっている階層型プロテクション でも、プロテクションの階層間でのやりとりには値(メッセージ)のコピーが必要であり、そのやりとりが増えるほど性能が低下することがわかっていた。
近年、L4 やK42といった新世代のマイクロカーネルが登場し、上述の性能問題をある程度解決している。
Windows NT系などの商用OSでよく見られる。Appleの macOS も、カーネギーメロン大学のMachとFreeBSDのモノリシックカーネルのコードをベースとしたXNUというハイブリッドカーネルを採用している。マイクロカーネルの性能オーバヘッドを削減するため一部のサービス(通信プロトコルスタックや)をカーネル空間で動作させるが、一部のカーネルコード(デバイスドライバなど)はサーバとしてユーザ空間で実行する。これは、純粋なマイクロカーネルが高性能を提供できると示される以前、妥協的に考案された技法であり、マイクロカーネルにモノリシックカーネルの特性を一部取り入れて拡張したものと言える。
ハイブリッドカーネルではカーネルがモジュール化されているが、モジュールの大部分は同じカーネル空間内にロードされる。そのため、バグを含むモジュールをロードするとカーネルの動作が不安定になる可能性がある。マイクロカーネルの場合、カーネルとは全く別の空間でモジュールを動作させることができ、安全に評価することができる。モノリシックカーネルと比較したハイブリッドカーネルの長所を以下に挙げる。
モジュールの開発期間が短い。(カーネルが不安定にならない限り)評価の際にリブートが不要である。カーネル全体の再コンパイルが不要である。
サードパーティーのテクノロジーを素早く統合できる。
モジュール群は何らかのモジュールインタフェースを使ってカーネルとやりとりする。そのインタフェースはOS固有ではあるが汎用化されており、常にモジュールとして分離実装できるわけではない。デバイスドライバにはモジュールインタフェース以上の柔軟性が必要なことが多い。基本的にモノリシックカーネルではカーネルとの呼び出しが1回で済むところを、ハイブリッドカーネルでは2回呼び出す必要がある。モジュール化の短所として次の事柄が挙げられる。
インタフェースを通る回数が増えるため、バグを作りこむ可能性も増加する(セキュリティホールも多い可能性がある)。
システム管理者はモジュール群の保守において混乱をきたす可能性がある。
ナノカーネルは全てのサービスをデバイスドライバとして分離する。これには例えば最も基本的な割り込みコントローラやタイマーの制御も含まれる。これによりカーネルメモリはマイクロカーネルよりもさらに小さくなる。
エクソカーネル (exokernel) はまだ実験段階のOS設計技法である。他のカーネルとの違いは、物理ハードウェアのプロテクションと多重化に機能を限定している点で、アプリケーションに対して全くハードウェアの抽象化を提供しない。このようにハードウェアのプロテクションをハードウェア管理から分離することで、利用可能なハードウェアを最大限に生かすように個々のプログラムを開発できるという利点が生じる。
エクソカーネル自体は非常に小さい。しかし、通常のOSの持つ機能をアプリケーション開発者に提供するためのライブラリ型OSを伴う。エクソカーネル型システムの最大の利点は、このライブラリ型OS機能を複数用意できるという点で、それぞれが異なるAPIを提供できる。例えば同じシステム上で、高度なUIを持つアプリケーションを開発し、同時にリアルタイムシステム制御を行うアプリケーションも開発できる。
厳密に言えば、オペレーティングシステム(とカーネル)はコンピュータを動作させるのに必須ではない。プログラムはマシン上に直接ロードされ実行されることも可能であり、そのようなプログラムはOSのサービスや抽象化なしで記述しなければならない。多くの初期のコンピュータではそのような手法が一般的であり、プログラムを入れ替えるときにリセットとリロードが必要だった。その後、プログラムローダーやデバッガといった補助的な小さなプログラムがメモリに常駐したり、ROMからロードされるようになった。これらが初期のオペレーティングシステムのカーネルの元となった。直接実行の手法は今日でもゲーム機や組み込みシステムで使われているが、一般に最近のコンピュータではオペレーティングシステムとカーネルが使われている。
1969年の RC 4000 Multiprogramming System では、小さな中核部の上で異なる目的のOS群を整然とした方法で構築するというシステム設計哲学を導入しており、マイクロカーネル方式のさきがけとなっている。
UNIX以前の10年間、コンピュータは劇的に能力を向上させ、マシンの未使用時間を使う手法が求められた。この期間の主な開発のひとつがタイムシェアリングシステム (TSS) である。TSSは何人かのユーザーがCPUのタイムスライスをそれぞれ割り当てられる。
タイムシェアリングシステムの開発は多くの問題を発生させた。ひとつの問題は大学のユーザーはCPU時間が欲しいというよりもシステムをハックしたがっているという点である。このためセキュリティやアクセス制御が1965年のMulticsプロジェクトの重要な課題となった。もうひとつの問題は計算リソースの正しい扱い方である。ユーザーは計算リソースを使わずに画面を凝視することにほとんどの時間を費やしており、タイムシェアリング方式ではそのようなCPU時間を他のユーザーに与えるべきと考えられた。最終的に、メモリ階層の多層化が進み、リソースの分割が仮想記憶システムの開発へと繋がっていったのである。
UNIXの設計段階で、全ての高レベルのデバイスをとして抽象化することが決定された。何故ならUNIX設計者は情報処理の目的をデータの変換であると考えていたからである。
例えば、プリンターもファイルとして抽象化され、データをそのファイルにコピーすると印字が行われる。他のシステムでは同様の機能を提供するにあたって、デバイスを低レベルに抽象化する傾向があった。デバイスもファイルも何らかの低レベルの概念の実体化である。システムをファイルのレベルで仮想化したことにより、ユーザは既存のファイル管理機能と概念で全てを扱うことができるようになり、操作が大幅に簡略化された。同じパラダイムを拡張して、UNIXはファイルを複数の小さなプログラムで操作するパイプの概念を可能とした。最終的な結果は同じであっても、このような小さなプログラム群を使うことで柔軟性が劇的に向上しただけでなく、開発も利用も容易になった。
UNIXでは、オペレーティングシステムは2つの部分で構成される。様々な操作を実行するユーティリティプログラム群とカーネルである。プログラミングの観点から見ると両者の違いは小さい。カーネルは特権モードで動作するプログラムであり、プログラムローダーとしての役割とシステムの残りの部分を構成するユーティリティプログラム群を監督する役割を持つ。そして、それらプログラムにロックと入出力サービスを提供する。つまり、カーネルはあらゆる場面に介在しているわけではなかった。
その後、計算モデルが変化し、UNIXの何でもファイルで表す手法が常に適用可能な方法ではなくなってきた。端末はファイルで表せるが(どちらも文字列を読み書きできる)、GUIはそのように扱うことはできない。コンピュータネットワークは別の問題を提起した。ネットワーク経由の通信はファイルアクセスに対応させることができるが、低レベルのパケット指向アーキテクチャはファイルというよりも離散的なデータの塊として扱う必要がある。コンピュータの機能が拡大するにつれ、UNIXのコードは増大していった。それはまた、UNIXカーネルのモジュール性が非常にスケーラブルなためでもあった。初期のカーネルのソースは10万行ほどだったが、Linuxカーネルなどでは1300万行にもなっている。
現代のUnix系OSは、モノリシックカーネルにモジュールローディング機能を加えたものとなっている。例えば、Linuxカーネルを採用した各種Linuxディストリビューションや、BSDの子孫である FreeBSD、DragonFly BSD、OpenBSD、NetBSD、macOS などがある。
Appleは1984年、最初のMac OSを同社のパーソナルコンピュータMacintoshに同梱して発売した。後継のmacOSはDarwinをベースとしており、4.4BSDユーザーランドとMachカーネルを統合したXNUと呼ばれるハイブリッドカーネルを採用している。
Microsoft Windowsは1985年、MS-DOSへのアドオンとしてリリースされた。他のOSに依存していたため、Windows 95までのリリースはOSではなくオペレーティング環境とみなされている。その製品ラインは発展して、Windows 9x系となり(32ビット化やプリエンプティブ・マルチタスクといった強化を経て)、最終的に2000年にWindows Meがリリースされた。マイクロソフトはまた、ハイエンド向けにWindows NT のラインも1993年の Windows NT 3.1からスタートさせ、こちらは2000年以降も続いている。
2001年10月にリリースされたWindows XPでWindows 9x系を置換して一般ユーザー向けOSが一新された。Windows NT系のカーネルはWindow ManagerやIPC Managerとクライアント・サーバ型階層型サブシステムモデルを採用しており、ハイブリッドカーネルとみなされている。
汎用マイクロカーネルとしてはカーネギーメロン大学が1985年から1994年まで開発したMachが有名だが、特定用途向けにもいくつかのマイクロカーネルが開発された。L4はマイクロカーネルの性能が悪くないことを実証するために作られた。ここから派生した新たな実装の Fiasco や Pistachio はLinuxをその上で動作させることができる。
QNXはマイクロカーネル設計を採用したリアルタイムオペレーティングシステムであり、1980年代初期に開発され、Machよりも遥かに成功している。ソフトウェアが不正作動することが致命的な状況で使われることが多く、スペースシャトルのロボットアームの制御やガラスを精密に磨く機械の制御で使われている。
Andrew Tanenbaum, Operating Systems – Design and Implementation (Third edition);
Andrew Tanenbaum, Modern Operating Systems (Second edition);
Daniel P. Bovet, Marco Cesati, The Linux Kernel;
David A. Peterson, Nitin Indurkhya, Patterson, Computer Organization and Design, Morgan Koffman (ISBN 1-55860-428-6);
B.S. Chalk, Computer Organisation and Architecture, Macmillan P.(ISBN 0-333-64551-0).
Houdek, M. E., Soltis, F. G., and Hoffman, R. L. 1981. . In Proceedings of the 8th ACM International Symposium on Computer Architecture. ACM/IEEE, pp. 341–348.