カーネル
しかしマイクロカーネルでは、サーバがクラッシュしてもそのサービスを再起動することでシステム全体のクラッシュを防ぐ可能性がある。しかし、現にLinuxなどのモノリシックカーネルは年単位で安定動作している実績があり、このようなマイクロカーネルの利点がどれほど重要かは疑わしい。
ネットワーキングなどのカーネルサービスは「サーバ」と呼ばれるユーザ空間のプログラムとして実装される。サーバを停止・再起動するだけでOSを更新可能である。たとえばネットワークをサポートしていないマシンで、ネットワークサーバは起動する必要がない。サーバ群やカーネルの間でデータをやり取りする作業があるため、モノリシックカーネルにはないオーバヘッドが生じ、効率が低下する。
マイクロカーネルの短所はたとえば次のようなものがある。
全体としてメモリをより多く使用する。
インタフェースを持つソフトウェアの数が多く、性能低下の可能性がある。
サーバ群とカーネル間のメッセージングにバグがあると、検出が困難である。
プロセス管理は一般に非常に複雑になりうる。
使用状況によってはマイクロカーネルは不利になる。単一用途のシステムでは動作するプロセス数が小さいため、マイクロカーネルがよく機能し、プロセス管理の複雑さもあまり問題にならない。
マイクロカーネル方式では、OSの他の部分を通常のアプリケーションのように高水準言語で書くことができ、同一のカーネル上で異なるOS(のインタフェース)を使用することができる。また動的にOSを切り換えたり、複数のOSを同時に使用することもできる。
モノリシックカーネルでは、全OSサービスはひとつのカーネル空間内に存在し、カーネルスレッド上で実行される。この手法は強力なハードウェアアクセスを提供する。UNIXの開発者ケン・トンプソンは、モノリシックカーネルの方がマイクロカーネルより実装が容易だとしている。主な欠点はシステム構成要素間の依存関係の複雑さである。たとえば、デバイスドライバにバグがあっただけでシステム全体がクラッシュするし、大きなカーネルは保守が非常に困難である。
Unix系OSが伝統的に採用してきたモノリシックカーネルは、OS中核機能とデバイスドライバを全て含んでいた。デバイスドライバ、スケジューラ、メモリ管理、ファイルシステム、ネットワークのプロトコルスタックなど、多くのプログラムが必要とするがライブラリとしてユーザー空間で実行することができない機能は、全てカーネル空間に置かれた。それら全サービスへのアクセスを可能にするため、数多くのシステムコールがアプリケーションに対して提供されている。
必要とされないサブシステムを伴って最初からロードされるモノリシックカーネルは、より汎用的な意味ではあるが、特定ハードウェア向けに設計されたものよりもチューニングが可能である。LinuxやFreeBSDなどの現代のモノリシックカーネルはUnix系OSであり、実行時にモジュールをロードする機能を備えており、必要に応じて容易に機能を拡張でき、同時にカーネル空間で動作するコード量をなるべく最小に抑えることができる。
カーネル設計において重要な観点として、障害(フォールトトレラント性)と悪意ある動作(セキュリティ)からの保護(プロテクション)サポートがある。この2つは通常明確には区別されず、明確に区別しようとするとリングプロテクションでは対応できなくなる。
カーネルが提供する機構または方針は、いくつかの基準で分類できる。
静的(コンパイル時に決定)か動的(実行時に決定)か
プリエンプティブか事後検出か
それらが満足する保護原理による分類(デニング)
ハードウェアサポートによる保護か言語サポートによる保護か
オープンな機構によるものか、方針と密に結合しているか
などである。
階層型プロテクションは、一般に「CPUモード」でサポートされる。ハードウェアサポートによる単純で効率的な方法は、MMUにメモリアクセスのたびにその妥当性をチェックさせるもので、その機構をケイパビリティベースドアドレッシング(英語版)と呼ぶ。ただし、多くの商用コンピュータアーキテクチャではMMUがケイパビリティをサポートしていない。
代替手法は、階層型プロテクションでケイパビリティをシミュレートするものである。この場合、保護されたオブジェクトはアプリケーションがアクセスできないアドレス空間になければならない。カーネルもそのようなメモリ空間のケイパビリティのリストを保持する。ケイパビリティによって保護されたオブジェクトにアプリケーションがアクセスしたい場合、システムコールを行い、カーネルが実際のアクセスを代行する。
カーネル(英: kernel)は、階層型に設計されたオペレーティングシステム (OS) の中核となる部分で、アプリケーションとハードウェアの架け橋である。具体的には、システムのリソースや、ハードウェアとソフトウェアの連携を管理する。そのほか、通信制御を行うことが多い。
オペレーティングシステムの基本コンポーネントとして、カーネルはメモリ、CPU、入出力を中心としたハードウェアを抽象化し、ハードウェアとソフトウェアがやり取りできるようにする。また、ユーザープログラムのための機能として、プロセスの抽象化、プロセス間通信、システムコールなどを提供する。
これらのタスクはカーネルによって方式が異なり、設計や実装も異なる。モノリシックカーネルは全てを一つの仮想アドレス空間に格納されたコードで実行して性能を向上させようとする。マイクロカーネルはサービスの大部分をユーザー空間で実行し、コードの保守性とモジュール性を向上させようとする。多くのカーネルはこの二つのカテゴリのいずれか、あるいは中間である。
モノリシックカーネルはコード全体を同じアドレス空間(カーネル空間)に置くよう設計されており、一部の開発者はシステム性能向上に必須の特徴だとしている。一部の開発者はうまく書けばモノリシックカーネルは極めて高効率になるとしている。
1980年代から1990年代初めにかけてのマイクロカーネルの性能は低かった。そういった初期のマイクロカーネルの性能を実測する研究が行われたが、性能が低い原因を深く分析することはなかった。そういったデータが一人歩きし、カーネルモードとユーザモードの切り替え回数が増え、プロセス間通信の回数が増え、コンテキストスイッチの回数が増えたためだ とみなされた。
そして1995年、マイクロカーネルの性能が低い原因として以下のことが推測されている。
マイクロカーネル「方式」全体が実際には非効率
マイクロカーネルで実装された「コンセプト」が非効率
それらコンセプトの特定の「実装」が非効率
この時点でマイクロカーネルを効率化する方法はまだ研究途上であり、正しい技法の構築が求められていた。
一方でモノリシックカーネルの設計の基盤となっている階層型プロテクション でも、プロテクションの階層間でのやりとりには値(メッセージ)のコピーが必要であり、そのやりとりが増えるほど性能が低下することがわかっていた。
近年、L4 やK42(英語版)といった新世代のマイクロカーネルが登場し、上述の性能問題をある程度解決している。
カーネルが巨大化するにつれて、さまざまな問題が明らかになってきた。最も明らかな問題はカーネルの大きさ(メモリ使用量)の増大である。これは仮想記憶をカーネル空間にも適用することである程度まで和らげられるが、全てのコンピュータ・アーキテクチャが仮想記憶をサポートできるわけではない。カーネルのサイズを削減するため、不要なコードを削除するなどの改善が必要となるが、これはカーネルの各モジュール間の明らかにされていない依存関係があるために非常に困難である。
マイクロカーネルと比較したときのモノリシックカーネルのさまざまな欠点から、1990年代の初期までにモノリシックカーネルは時代遅れと考えられるに至った。結果としてLinuxがモノリシックカーネルを採用したことでリーナス・トーバルズとアンドリュー・タネンバウムの間で有名な論争が発生した(アンドリュー・タネンバウムとリーナス・トーバルズの議論)。
すなわち、この分離が不適切であることが既存のOSで本質的技術革新が見られないことの主要因だとし、コンピュータアーキテクチャにおける共通課題だとした。モノリシック設計は、従来の商用システムで一般的な保護技法である「カーネルモード」と「ユーザーモード」に分離するアーキテクチャ(いわゆるリングプロテクション)から生まれた。そのアーキテクチャでは、保護(プロテクション)を必要とするモジュールを可能な限りカーネルに含めようとする。このようなモノリシック設計と特権モードの関係が機構と方針の分離における重要な問題として再注目されている。実際「特権モード」のアーキテクチャ技法は保護機構とセキュリティ方針を融合させる傾向があるが、これとは大きく異なるアーキテクチャ技法であるケイパビリティベースドアドレッシング(英語版)ではその2つを明確に区別し、自然にマイクロカーネル設計が可能となる。
モノリシックカーネルはカーネルの全コードを同じアドレス空間(カーネル空間)で実行するが、マイクロカーネルでは多くのサービスをユーザー空間で実行しようとし、コードベースの保守性とモジュール性を向上させようとしている。多くのカーネルは明確にどちらかに分類できるわけではなく、その中間の実装ともいうべきハイブリッドカーネルになっている。さらに特殊な設計としてナノカーネルやエクソカーネルが研究されているが、広く使われるまでには至っていない。エクソカーネルの例としてXenハイパーバイザがある。
モノリシックカーネルと比較したハイブリッドカーネルの長所を以下に挙げる。
モジュールの開発期間が短い。(カーネルが不安定にならない限り)評価の際にリブートが不要である。カーネル全体の再コンパイルが不要である。
サードパーティーのテクノロジーを素早く統合できる。
モジュール群は何らかのモジュールインタフェースを使ってカーネルとやりとりする。そのインタフェースはOS固有ではあるが汎用化されており、常にモジュールとして分離実装できるわけではない。デバイスドライバにはモジュールインタフェース以上の柔軟性が必要なことが多い。基本的にモノリシックカーネルではカーネルとの呼び出しが1回で済むところを、ハイブリッドカーネルでは2回呼び出す必要がある。モジュール化の短所として次の事柄が挙げられる。
インタフェースを通る回数が増えるため、バグを作りこむ可能性も増加する(セキュリティホールも多い可能性がある)。
システム管理者はモジュール群の保守において混乱をきたす可能性がある。
エドガー・ダイクストラは論理的観点から、バイナリセマフォにおける不可分なロックとアンロック操作だけで、プロセス間の任意の協調作動を実現できることを証明した。しかしそのような方式は一般に安全性や効率性が欠如しており、メッセージパッシング方式の方が柔軟性が高い。他の方式もいくつかあり、現代のカーネルでは共有メモリやRPCなどのシステムをサポートしていることが多い。