Operating Systems Development Series
Kernel: Basic Concepts Part 2
by Mike, 2008, 2009

はじめに

ようこそ!:)

前回のチュートリアルで、多くの概念を取り上げました。このチュートリアルでは、これらの概念を引き続き見ていきます。 このチュートリアルでは、非常に重要な概念をたくさん見ていくことになります。今日のメニューは以下の通りです。

  • ハードウェアの抽象化
  • カーネル新しい視点
  • カーネル設計抽象化:主要な設計モデル
  • カーネルのデザイン概要: 二次設計モデル
このチュートリアルでは、ブートローダとカーネル設計の初歩の間の接着剤について説明します。このチュートリアルは、カーネルが本当は何なのか、そして私たちが何をする必要があるのかを理解するために、すべてをまとめる接着剤となるでしょう。

ここで挙げたすべてのコンセプトは、次の数回のチュートリアルで非常に重要なものとなります。

それでは、快適なシートでくつろぎながら、もうひとつの楽しいチュートリアルを見てみましょう!そうそう、このチュートリアルはそんなに大きくないのがいいところです :)

エキソカーネルについて説明するセクションを追加する予定です。これは本当に新しいカーネル設計の概念です。このシリーズでこの設計を実装する予定はありませんが、読者はこのカーネル設計に興味を持つかもしれないと感じています。もしかしたら、この設計を自分のOSで使うかもしれません。

準備はいいですか?

ハードウェアの抽象化

ハードウェアの抽象化は非常に重要です。ここまでで、ハードウェアプログラミングがいかに複雑か、そしていかにハードウェアに依存しているか、おわかりいただけたと思います。そこで登場するのが、HAL(Hardware Abstraction Layer)です。

HALは、物理的なハードウェアへのインタフェースを提供するために使われるソフトウェアの抽象化レイヤーです。特定のデバイスやコントローラの詳細を知らなくても、デバイスと対話できる方法を提供する抽象化レイヤーです。

通常、最近のOSでは、HALは基本的なマザーボードのチップセットドライバである。これは、カーネルと、プロセッサを含むマシンのハードウェアとの間の基本的なインターフェイスを提供します。これは、カーネルがハードウェアにアクセスする必要があるときにいつでもHALと対話することができるので、素晴らしいことです。これはまた、カーネルが完全にハードウェアから独立できることを意味する。

また、特定のコントローラやマッピングではなく、デバイスそのもので考えることができます。これは、カーネル自体をよりクリーンにすることにもつながります。

もう一つの大きなメリットは、抽象化そのものにあります。もし、私たちのOSを異なるハードウェアを搭載したシステムに移植することになった場合、必要なのはそのシステム用に新しいHALを開発することだけです。これは、HALがこれを可能にするように非常にうまく設計されていることが前提です。

最近のOSのほとんどは、何らかの形でHALを利用しています。私たちはまた、チップセットのハードウェアとカーネルの間で、マザーボードのチップセットドライバとして機能するHALを開発する予定です。次のチュートリアルでは、HAL の背後にあるプロセッサ自体を抽象化し、HAL の開発を開始する予定です。

カーネル新しい視点

では、Kernelとはいったい何なのでしょうか。KernelはJohn N. Shutt (Serously ;) によって開発されたSchemeライクなプログラミング言語です。)

ともかく、別の定義を見てみましょう。カーネル」とは、システムの中心的な構成要素です。カーネルはシステムの中核であり、システムの効率的な実行を管理するための非常に基本的な機能を提供するものです。

オペレーティングシステムでは、この強力なカーネルが、システムのハードウェアとリソースに対する最も基本的なインターフェースを提供し、プロセッサ管理、I/O管理、メモリ管理、プロセス管理などの最も基本的な管理機能も提供します。カーネルは、開発するシステムの複雑さに応じて、より多くの機能を含むことができます。

よりよく理解するために、もう少し詳しく見てみましょう。

カーネル。すべてを統合する

メモリ管理

メモリ管理とは、以下のようなものです。

  • メモリを要求するプログラムに対して、動的にメモリを与えたり、使ったりすること。
  • ページングや仮想メモリを実装する。
  • OSカーネルが未知のメモリや無効なメモリに読み書きしないようにすること。
  • メモリフラグメンテーションの監視と処理
メモリ保護とは、以下のようなものです。
  • プロテクトモードでの無効なディスクリプタへのアクセス(あるいは無効なセグメントアドレスへのアクセス)
  • プログラム自体の上書き
  • メモリ上の他のファイルの一部または全部を書き換える。

カーネルはリング0で動作しているため、メモリ内のすべてのバイトを直接制御できることを忘れないでください。 また、これはすべて物理メモリ上で直接動作していることを忘れないでください。もし、メモリが足りなくなったらどうなるのでしょうか?存在しないメモリに書き込んだらどうなるのでしょう?ハードウェアデバイスが使用するメモリロケーションはどうなるのか?また、メモリ上に存在する「隙間」にも触れません。

警告。物理メモリにランダムに書き込むと、(書き込む場所にもよりますが)誤動作を引き起こしたり、(そのメモリ領域を使用しているハードウェアデバイスによっては)システムが起動できなくなり、全く使い物にならなくなる可能性があります。(BIOSのデータ領域に書き込むと、その領域によっては誤動作を起こす可能性があります。

このようなことを考えると、物理メモリを適切に管理することがいかに重要であるかがわかると思います。

物理メモリを適切に管理するKernelは、アプリケーションとメモリとの間に仮想的なインタフェースを作ることができます。これは、ユーザースペースと カーネルスペースのコードとデータを分離することと、Virtual Addressingによって実現されます。

物理メモリで直接実行することには多くの問題があるため、より良い方法でメモリをエミュレートすることができます。メモリエミュレーション(仮想メモリ)は、物理RAMよりもはるかに多くのメモリを持つシステムをエミュレートすることができ、各アプリケーションは独自の仮想メモリアドレス空間を使用します。

プロセッサー管理

これは新しいものです。ご存知のように、BIOS ROMはプライマリ・プロセッサを初期化し、起動させます。シングルコアしか起動しません。 もし、ミューティコアプロセッサを搭載したシステム、またはマルチプロセッサを搭載したシステムでOSを起動している場合は、他のプロセッサやコアを手動で起動させる必要があります。

アプリケーションにいつでも異なるプロセッサを使わせると、システムの致命的な問題を引き起こす可能性があります。このため、アプリケーションにこのような機能を持たせてはいけません。

I/Oデバイス管理

物理メモリと同様に、アプリケーションがコントローラのポートやレジスタに直接アクセスすると、コントローラが誤動作したり、システムがクラッシュしたりする可能性があります。このため、デバイスの複雑さによっては、プログラミングが驚くほど複雑になり、数種類のコントローラを使用するデバイスもあります。このため、デバイスを管理するための抽象的なインタフェースを提供することが重要です。 このインタフェースは通常、デバイスドライバまたはハードウェア抽象化レイヤによって行われます。これによって、デバイスの詳細ではなく、デバイスの観点から考えることができるようになります。

頻繁に、アプリケーションはこれらのデバイスへのアクセスを必要とします。カーネルは、何らかの方法でシステムに問い合わせることで、これらのデバイスのリストを管理しなければなりません。アプリケーションがデバイスに対する操作を要求すると(例えば、文字を表示するなど)、カーネルはこの要求を現在アクティブなビデオドライバに送信する必要があります。ビデオドライバは、この要求を実行する必要があります。これは、プロセス間通信(IPC)の例です。

プロセス管理

これが「カーネル」の最も重要な仕事であり、あらゆるコンピュータの仕事でもある。カーネルは、実行時間を割り当て、異なるアプリケーションやプロセスを実行・管理する方法を必要とします。

プログラム管理は次のような役割を担っています。

  • プログラムが他のプログラムの上に書き込まれないようにする。
  • プログラムが他のプログラムを上書きしないようにする。
  • プログラムからのタスク完了の要求(メモリの確保や解放など)を処理する。
マルチタスクとは、以下のことを指します。
  • 複数のプログラムを切り替えて、一定の時間枠で実行させる。
  • スイッチングを可能にするタスクマネージャを提供する(Windowsタスクマネージャなど)。
  • TSS (Task State Segment) スイッチング。これも新語
  • 複数のプログラムを同時に実行すること。
アプリケーションを実行するために、カーネルはアプリケーション独自の仮想アドレス空間(VAS)を設定し、VASにファイルをロードする必要があります。カーネルは次にアプリケーションのスタックを設定し、実行を開始するためにそれにジャンプします。

Virtual Addressingによって、アプリケーションがシステムメモリの問題に直面しないようにする。

マルチタスクシステムでは、タスクマネージャが各プロセスに一定の時間を割り当て、その時間内にのみ実行させる。そして、実行中のアプリケーションを切り替えていきます。このとき、割り当てられる時間が短いため、タスクマネージャは実行中のプロセスをすばやく切り替えることができ、複数のプロセスが同時に動作しているように見せかけることができます。

これは、ハードウェアまたはソフトウェアで行うことができます。プロセッサは、TSS(Task State Segment)レジスタを使用してハードウェアのタスク切り替えをサポートしています。

システムAPI

アプリケーションはどのようにしてデバイスやシステムリソースへのリクエストをカーネルに要求するのでしょうか?これまでOSがアプリケーションを管理・制御する方法について見てきましたが、アプリケーションはどのようにシステムを制御するのでしょうか。

そこで登場するのが、システムのAPI(Application Programming Interface)です。システムAPIは、アプリケーションがカーネルや他のシステムソフトウェアと対話するために使用するAPIです。

システムAPIを作成するための方法はたくさんあります。ほとんどのシステムは、割り込みを通じてシステムAPIルーチンをサポートしています。例えば、LinuxカーネルのシステムAPIは主にシステムルーチンのために割り込み番号0x80を使用します。

まとめ

うわー、すごい量ですね。まだ理解できなくても心配しないでください。すぐに理解できるようになりますから :)

カーネル設計 - 概要: 主な設計モデル

ここまで来ると、カーネルがいかに重要か、そしてカーネルがどこに位置するのかが分かってくるかもしれません。

これまで多くのオペレーティングシステムが、多くの異なる設計とセットアップを用いて開発されてきました。これらの設計の多くは、いくつかの類似した基本的な概念を持っています。

カーネルを構築する方法は実にさまざまです。ここでは、より使用される設計のいくつかを見ていきます。

モノリシックカーネル設計

Monolithic Kernelでは、すべてのシステムプロセスがRing 0でKernelの一部として実行されます

最初の部分--「Mono」は「1つ」という意味だ。2つ目の「lithic」は「石の、石のような」という意味です。

Monolithicカーネルでは、全体のカーネルは、リング0のカーネル空間で実行されます。また、システムAPIを介して基本的なシステムコールのセットを提供します。

モノリシックカーネルでは、(すべてではないにしても)ほとんどのカーネルサービスは、カーネル自体の一部です。これは、各サービスが互いに独立できないことを意味するものではありません。しかし、ソフトウェアはカーネルの残りの部分と非常に緊密に統合されています。このため、モノリシックカーネルは他の設計と比較して非常に高速で効率的です。

OSのサービスはすべてカーネルの一部として(あるいはカーネルの拡張として)カーネル空間で実行されるため、デバイスドライバやシステムサービスプログラムに問題があると、システム全体がクラッシュする可能性があります。

アプリケーションがシステムサービスを要求する場合、System APIを通じてシステムコールを実行します。

Examples

いくつかの大規模なオペレーティングシステムはハイブリッドカーネルを使用していますが、これらに限定されるものではありません。
  • Unix-like kernels
    • Linux
    • Syllable
    • Unix kernels
      • BSD
        • FreeBSD
        • NetBSD
    • Solaris
    • AI
  • DOS
    • DR-DOS
    • MS-DOS
      • Microsoft Windows 9x series (95, 98, Windows 98SE, Me)
  • Mac OS kernel, up to Mac OS 8.6
  • OpenVMS
  • XTS-400

マイクロカーネルの設計

マイクロカーネル設計では、カーネルはユーザーモードシステムサービスに必要な基本的な機能のみを提供します。

マイクロカーネルは、OSのサービスを全く提供せず、それらのサービスを実現するために必要なメカニズムだけを提供するカーネル設計です。 このため、カーネル自体は通常、モノリシックカーネルと比較して非常に小さくなっています。例えば、マイクロカーネルは、低レベルのメモリ管理、スレッド管理、プロセス間通信(IPC)などを実装することができます。

上の画像は、マイクロカーネルを表示しています。このカーネルは、基本中の基本のものしか実装していないことに注意してください。この場合、基本的なプロセス管理とスケジューリング、プロセス間通信(IPC)、および基本的な仮想メモリ管理を含意しています。

カーネルは、(モノリシックカーネルと同様に)カーネルの一部として実装されたすべてのものではなく、デバイスドライバやファイルシステムなどの外部のusermodeサービスを使用します。このため、外部サービスがクラッシュしても、システムはまだ機能している可能性があり、システムはクラッシュしません。

IPC(Inter Process Communication)とサーバーとデバイスドライバーを理解することは、マイクロカーネルの仕組みを理解する上で重要です。

マイクロカーネルサーバー

マイクロカーネルの「サーバー」は、通常のプログラムが持っていない特別な権限をカーネルから付与された外部プログラムです。この「特権」は、ハードウェアや物理メモリへの直接アクセスであったりする。これにより、サーバープログラムは、制御しているハードウェアデバイスと直接対話することができるようになります。待って、デバイスドライバのように聞こえるけど、そうなの?基本的にはそういうものです。

マイクロカーネルは非常に最小限のものであることを忘れないでください。彼らは外部のプログラム、つまりサーバに依存しています。

カーネル自身が必要とするサーバーは、通常、カーネルが実行される前にメモリにロードされます。例えば、ファイルシステムサーバは、ファイルシステムをパースするためのコードを含んでいる必要があります。カーネルはファイルシステムのコードを持たないので、ファイルシステムサーバをロードする方法がないのです!このため、カーネルが実行される前に、ファイルシステムサーバをロードする必要があります。

どうすればいいのでしょうか?いくつかの方法があります。ひとつは、カーネルとサポートされるサーバの両方を含む完全な RAM イメージをその中にロードする方法です。もう一つは、起動時にブートローダで必要なサーバをロードしておき、実行時に何らかの方法でサーバ情報をカーネルに与える方法です。どちらの場合も、ブートローダはどのファイルシステムローディングコードを使うかを決めることができますが、そのコードはそもそもロードする必要がなくファイルシステムサーバと対話することができます!クールでしょう?

注意: 「サーバ」は「デーモン」とも呼ばれることがあります。

プロセス間通信(IPC)

IPCはマイクロカーネルで非常に重要です。IPCは、別々のプロセスが互いに通信することを可能にします。通常はメッセージを送信しますが、共有メモリを使用することによっても可能です。

あるプロセスが他のプロセスに「シグナルを送る」方法はたくさんあります。マイクロカーネル・サーバーに関して言えば、最も一般的に使われているのは、最も理解しやすい方法の一つであるメッセージパッシングです。

IPCは、サーバとカーネルが相互に作用することを可能にします。

同期型IPC(Synchronous IPC

Synchronous IPCでは、メッセージを送信したプロセスは、相手プロセスから応答があるまで中断されます。相手プロセスが忙しい場合、メッセージはキューに格納され、そのプロセスが準備ができ次第、対応できるようにする。

非同期IPC

Synchronous IPCに似ているが、両方のプロセスが実行され続ける。つまり、プロセスは中断されない。

カーネル設計 - 概要:二次設計モデル

カーネルを設計する方法は無数にあることを忘れないでください。以下は、主要な設計モデル(モノリシックカーネルとマイクロカーネル)から派生した一般的な設計モデルです。

ハイブリッドカーネル

ハイブリッドカーネルは、マイクロカーネルにモノリシックカーネルの側面を取り入れたものです

ハイブリッドカーネルは、モノリシックカーネルとマイクロカーネル設計の両方の側面を組み合わせたカーネルです。

ハイブリッドカーネルは、通常、マイクロカーネルに似た構造を持っていますが、モノリシックカーネルとして実装されています。より良く理解するために、これを別の方法で見てみましょう。

ハイブリッドカーネルは、マイクロカーネルと同様に、ファイルシステム、デバイスドライバなどのために別々のサーバープログラムを使用します。しかし、モノリシックカーネルと同様に、これらのサーバーはユーザースペースではなく、カーネルの一部として実行されます。

ハイブリッドカーネル」という用語が何に当てはまるかについては、いくつかの論争がある。マイクロカーネル」、「マクロカーネル」、「修正マイクロカーネル」、「修正マクロカーネル」と呼ばれることもある。ハイブリッドカーネルは、独自のデザインではなく、モノリシックカーネルからいくつかの側面を持つだけの変更されたマイクロカーネルです。そのため、ハイブリッドカーネルを何と呼ぶかについては、いくつかの論争がある。

MicrosoftのNTアーキテクチャは、彼らのカーネルデザインモデルにハイブリッドアプローチを使用しています。Microsoftは彼らのカーネルを「Modified microkernel」と表現している。

Examples

いくつかの大規模なオペレーティングシステムはハイブリッドカーネルを使用していますが、これらに限定されません。
  • BeOS Kernel
    • Haiku Kernel
  • BSD
    • DragonFly BSD Kernel
    • XNU Kernel
  • NetWare Kernel
  • Plan 9 Kernel
    • Inferno Kernel
  • Windows (NT,2000,2003,XP,Vista) NT Kernel
    • ReactOS Kernel

Nanokernel(ナノカーネル

ナノカーネルは、ピコカーネルとも呼ばれ、非常に小さなカーネルです。通常、これは最小のマイクロカーネル構造になります。 カーネル自体が非常に小さいため、システム内の基本的なリソースは他のソフトウェアやドライバに依存する必要があります。

おわりに

さて、このチュートリアルはそれほど複雑ではないことを認めざるを得ません。しかし、私たちがカバーする必要があった非常に重要なトピックをたくさんカバーしています。このチュートリアルが、カーネルとその役割について、読者がより良く理解するのに役立つことを期待しています。カーネルだけでなく、そのための基本的なハードウェア抽象化レイヤ(HAL)を構築することになるのです。

このシリーズでは、修正したマイクロカーネルを開発する予定です。これは、読者がモノリシックとマイクロカーネルの両方の設計の経験と理解を得ることができ、また、ハイブリッドマイクロカーネルへのアプローチを混合することができます。 実際、我々のカーネルは、このチュートリアルで表示されているものと似ているように見えるでしょう。次のチュートリアルでは、カーネルの完全な設計について触れ、C++ を使用してプロセッサの依存関係を抽象化するための HAL の基本的なビルディングブロックを開発する予定です。

今後は、複数のコンパイラとプラットフォームをサポートするために、いくつかのバージョンのデモを作成する予定です。また、C++とC言語の両方をサポートする予定です。どうですか?