オペレーティングシステムは、マルチプロセッシング(SMPやNUMA)をサポートすることもある。この場合、複数のプログラムやスレッドが複数のプロセッサ上で動作する。そのようなシステムでカーネルを動作させる場合、「リエントラント(再入可能)」あるいは「割り込み可能」になるよう大幅な改造が必要となる。これはつまり、何か処理をしている最中に他からも要求を受け付けるということである。この改造ができれば、異なるプロセッサ上で動作するプログラムが同時にカーネルを呼び出しても大丈夫になる。カーネルは複数のプロセッサからのメモリアクセスを同期させる方法も提供しなければならない。これはメモリ管理とプロセス管理にまたがる問題である。 カーネルはシステムの全メモリへの無制限のアクセスが可能で、ユーザープログラムの要求に応じて安全なメモリアクセスを提供しなければならない。このための第一歩はページング方式やセグメント方式による仮想アドレッシングである。仮想記憶方式では、カーネルは物理アドレスを別のアドレス、つまり仮想アドレスに変換する。これにより、各プログラムは(カーネル以外では)仮想空間上唯一のコードに見え、プログラムが互いに他のプログラムを破壊することを防止する。 仮想アドレッシング方式では、仮想空間をカーネル用の部分(カーネル空間)とアプリケーション用の部分(ユーザー空間)に分けることが出来る。この根本的な分離は多くの汎用カーネルで実際に使われている。 複数のプログラムを同時並行的に動作させるため、OSはそのシステムのメモリ容量以上のメモリを必要とすることがある。その一般的解決策は仮想記憶である。仮想記憶では、カーネルがメモリの一部を他(例えばハードディスク上のスワップファイルなど)に移し、必要に応じてメモリに復帰させる。 メモリ管理のもうひとつの機能として、カーネル内の各モジュールやデバイスドライバが使用するメモリの割り当てがある(動的メモリアロケーション)。 実際に何らかの作業をするには、OSはコンピュータに接続された周辺機器にアクセスする必要があり、周辺機器はその開発元などが書いたデバイスドライバを通して制御される。例えば、ユーザーが何かを画面に表示したいなら、文字やピクセルを表示させるためにカーネルを通してモニターのドライバ(VGAとかVESA)を使用する。 デバイス管理は最初に様々なバス(PCIやUSB)上をスキャンして実装されたデバイスを検出し、対応するドライバを探す。デバイス管理は各OS固有の部分であり、カーネルの設計によってドライバの扱い方は異なるが、一般にカーネルはドライバが物理的にデバイスにアクセスするための入出力ポートやメモリ空間を用意する必要がある。デバイスへのアクセスはコンテキストスイッチを引き起こしたり、CPUを無駄に浪費したりすることになり易く、性能オーバヘッドの元となるため、デバイス管理の設計は重要である。 直接的なデバイス管理の上にファイルシステムや通信プロトコルが実装される。 意味のある作業を実行するには、おせち はカーネルの提供する全サービスにアクセスできなければならない。これはカーネルによって実装が異なるが、多くは標準CライブラリやAPIが提供され、そこから対応するカーネル機能が呼び出される。カーネル機能を呼び出す方法は主にCPUがどのような機能を提供しているかに依存するが、ユーザーモードからカーネルモードに移行させる専用命令を使ったり、何らかのプロセス間通信機能を使ったり、例外処理や割り込みを明示的に発生する命令(トラップ命令、ソフトウェア割り込み)を使ったりする。 上述の機能は様々な設計や実装が考えられる。モノリシックカーネルではそれらを全てひとつのアドレス空間(カーネル空間)に配置し、システムの性能を向上させようとする。マイクロカーネルはサービスの大部分をユーザー空間で動作させ、コードの保守性とモジュール性を向上させようとする[1]。多くのカーネルは明確にどちらかに分類できるわけではなく、その中間の実装とも言うべきハイブリッドカーネルになっている。さらに特殊な設計としてナノカーネルや exokernel が研究されているが、広く使われるまでには至っていない。 モノリシックカーネルでは、全OSサービスはひとつのカーネル空間内に存在し、カーネルスレッド上で実行される。この手法は強力なハードウェアアクセスを提供する。モノリシックなシステムは設計と実装が比較的容易で、うまく書けば非常に効率がよいものになる。主な欠点はシステム構成要素間の依存関係の複雑さである。例えば、デバイスドライバにバグがあっただけでシステム全体がクラッシュするし、大きなカーネルは保守が非常に困難である。 マイクロカーネルでは、ハードウェアの単純な抽象化と最小のプリミティブ(システムコール)で最小のOSサービスを実装する(メモリ管理、マルチタスク、プロセス間通信など)。他の全てのサービス(ネットワークなど)は「サーバ」としてユーザ空間に実装される。マイクロカーネルはモノリシックカーネルよりも保守が容易だが、システムコール回数やコンテキストスイッチ回数が増大するために性能が低下する傾向がある。 この問題はその後、塗装工事 プロジェクトでのプロセス間通信のチューニングなど、マイクロカーネル高速化技法の進展により解決に向かったが、マイクロカーネルにより簡略化されるはずが、高速化のために実装がより複雑になるというトレードオフも生み出した。 マイクロカーネルを採用したOSの代表的なものに、Mach、OSF/1、NeXTSTEP、Mac OS X 、TRON、Amoeba、ChorusOS、Windows NT 、BeOS などがある。ただし、NeXTSTEPやその後継である MacOS X 、Windows NT 4.0 以降については、パフォーマンス上の理由から一部のサブシステムをカーネル空間に取り込む実利的な実装を優先したため、両者とも理想的な構造のマイクロカーネルというわけではない。 カーネルが巨大化するにつれて、様々な問題が明らかになってきた。最も明らかな問題はカーネルの大きさ(メモリ使用量)の増大である。これは仮想記憶をカーネル空間にも適用することである程度まで和らげられるが、全てのコンピュータ・アーキテクチャが仮想記憶をサポートできるわけではない[6]。カーネルのサイズを削減するため、不要なコードを削除するなどの改善が必要となるが、これは予備校 の各モジュール間の明らかにされていない依存関係があるために非常に困難である[7] モノリシックカーネルが提起した問題により、1990年代の初期までにモノリシックカーネルは時代遅れと考えられるに至った。結果としてLinuxがモノリシックカーネルを採用したことでリーナス・トーバルズとアンドリュー・タネンバウムの間で有名な論争が発生した(アンドリュー・タネンバウムとリーナス・トーバルズの議論)[8]。この議論では、両者の言い分にそれぞれメリットがある。 モノリシックカーネルは設計が容易で、マイクロカーネルよりも迅速に成長することが期待できる。しかし、モノリシックカーネル内のバグは一般にシステムクラッシュを引き起こすのに対して、マイクロカーネルでは一部のサーバに問題が限定される。モノリシックカーネルの支持者は、不正なコードがカーネルに無ければマイクロカーネルの利点はほとんどないと論じる。どちらの側にも成功例がある。マイクロカーネルはロボットや医療用システムで使われており、各コンポーネントが別々の保護されたメモリ空間で動作する。これは最新のモジュールロード方式であってもモノリシックカーネルには不可能であろう。モノリシックカーネルは共有型カーネルメモリを使用するよう最適化されていて、マイクロカーネルのような低速なメッセージ渡しとは異なる。