Linuxのカーネルの開発に関する世界観(開発)です。
言ってしまえば、Linuxカーネルの中核的な機能は3つに分けられます。すなわち、プログラムの「並列実行」、リソースすなわちディスクやメモリなどのキャッシュや再配分による「効率化」、そしてハードウェアIOデバイスやディスク・ネットワークなどの「機器の適切な操作」です。
Linuxカーネルは、レジスタの内容をメモリに退避しながら、スケジューリングアルゴリズムに基づいて次々と停止と再実行を繰り返すことで、ひとつのCPUしかないハードウェアにおいて、それぞれのプログラムの数だけCPUがあるかのように「仮想化」します。
メモリにおいては、それぞれのプログラムのメモリの数だけアドレス空間を用意するために、論理アドレスをリニアアドレスや物理アドレスに変換します。
このようにすることで、CPUやメモリを仮想的に複数作り出し、並列的に処理ができるようにします。割り込みやプロセス間通信やスレッドなども、この並列処理に関係する重要な機能です。
Linuxカーネル(プロセス)やLinuxカーネル(メモリ管理)を参照のこと。
また、Linuxカーネルは、プログラムのデータの読み込みや書き込みを効率化するために、キャッシュを行います。メモリ、ディスクストレージ、ネットワークなどにおいて、適切なキャッシュを行います。
i-nodeを書き込む際には、i-nodeを未使用、使用中、あるいはダーティ(書き込み中)の3つに分類することで、キャッシュに書き込まれた内容を後でディスクに書き込むようにします。
また、メモリにおいては、ページング機構とセグメンテーション機構を上手く使い、三段階のページアドレッシングを行い、ページ置換アルゴリズムなどを用いることで、効率的かつもっとも連続性の高いメモリ領域を確保します。
このようにすることで、リソースを効率的かつ高速に配分します。
Linuxカーネル(ファイルシステム)を参照のこと。
最後に、Linuxカーネルは、機器の適切な操作を行います。
ハードウェアの操作は、デバイスドライバレベルで見ると、とても複雑かつ異なる仕様を持っています。Linuxカーネルは、ハードウェアデバイスに対して、低レベルのデバイスドライバだけがそのデバイスコントローラの仕様を知っているようにし、プログラマには抽象的なレイヤーを用意して、隠蔽した上で簡単かつ共通の操作ができるようにします。
また、ネットワークなどの機能については、適切かつ効率的にネットワーク通信が行えるように、標準に準拠した、あるいは場合によっては標準仕様よりも効率的で優れたソケット通信のサブシステムを提供します。
また、IntelのCPUにおいては、さまざまな特権レベルを考慮し、カーネルモードとユーザモードを切り替えて実行します。Intel互換のCPUだけではなく、ほかのCPUアーキテクチャにもLinuxは対応し、ユーザーランドのプログラムがC言語で書かれる場合、カーネルがCPUアーキテクチャのレイヤーを共通化し、コンパイルし直すだけで別のアーキテクチャに対応できるようにします。
Linuxカーネル(デバイス)を参照のこと。
UNIXのカーネルは、CPUの「カーネルモード」と「ユーザーモード」によって、カーネルとユーザーの世界を分ける。
UNIXのユーザーランドのプログラムはユーザーモードで実行される。プログラムからシステムコールが呼び出されると、システムコールが実行されている間、そのプログラムはカーネルモードに切り替わる。システムコールの実行が終わると、その後にプログラムはユーザーモードに再度切り替わる。
カーネルモードとユーザーモードは、CPUの特殊な命令で切り替えられる。Intel のx86系CPUにはこのようなCPUの状態が4種類あるが、UNIXではカーネルモードとユーザーモードのみを使う。
ユーザーモードで実行されている時は、カーネル内のコードやデータにはアクセスできない。カーネルモードで実行中の時のみ、これらのリソースへのアクセスが許される。
詳しくは以下の書籍が参考になります。
2023.05.12編集
Linuxは基本的にコマンドラインのOSだが、その特徴として、MS-DOSなどのパソコン向けOSでは使えない、高機能で高度なコマンドラインシェルを使うことが出来る。
また、コマンドシェル・インターフェースは、ネットワークを通して使うことも出来る。
UNIX環境のため、端末として使うコンピュータ、ログインするコンピュータ、ファイル管理をするコンピュータなどを分けて構築することも、比較的容易である。
自動化も比較的容易で、シェルスクリプトやスクリプト言語のように、コマンドやシステムコール・Cや他言語の関数などをスクリプト形式で実行することも出来る。
簡単なコマンドなら、EmacsやVimのようなテキストエディタからも、コマンドを実行することが出来る。
また、最近はGUIのデスクトップ環境を使って、Windowsなどのパソコン向けOSと同等かそれ以上のデスクトップ機能を使うことも出来る。この場合、X11サーバーを最初に起動し、クライアントのGUIアプリケーションをXサーバーと通信させ、Xlibに対応したツールキットライブラリ(GTK+やQt)とともに使うことになる。
この場合、Windowsとは違って、さまざまなインターフェースを独自に開発することが出来る。代表例は、GNOMEとKDEである。
そして、オープンソースで開発されているアプリケーションは、Microsoft製品やAdobe製品などに勝るとも劣らない機能を持っている。(だが、操作性の違いにより戸惑う部分や、未完成で上手く動かないことも多い。)
Linuxカーネルは受動型のプログラムで、能動的に何かを実行することは無い。システムコールあるいは割り込みに応じて、応答を返して実行される、イベント駆動型のソフトウェアである。
カーネルのプログラムの役割としては、アプリケーションの実行(プロセス管理)と、システムとプログラムに対するメモリ管理、それからデバイスドライバーによるハードウェアの操作と監視、ストレージデバイスにおけるファイルシステムの実現、そしてネットワークへの接続などがある。
Linuxカーネルは、単一の巨大なプログラムとして実現されており、モノリシックカーネルと呼ばれる。これは、カーネルの機能をたくさんのサーバーやサービスに分ける、MinixやGNU Hurdのマイクロカーネルとは逆の方向である。Minixのタネンバウム教授もそれを批判している。だが、マイクロカーネルは性能的に遅いことがある。Hurdなどは、遅すぎて使い物にならない、と言う話もある。
詳しくは以下をご覧あれ:
カーネルでは、構造体とポインタ、そして膨大な関数によって、それぞれ局所的にとても複雑な計算をしています。
ですが、基本的に存在するのはif文とfor文であり、そこにさまざまな関数の呼び出しと構造体の数値の代入が行われています。
読み解くのにはとても技術力の基本力が必要だと思いますが、そんなに高いハードルではないと僕は思います。
C言語のプログラムをどのように書いていくか、ということの参考にもなるので、頑張って読もうとチャレンジしても僕は良いと思います。
Linuxカーネル(ソースコード・カーネルモジュール)を参照のこと。
LAMPスタックのようにLinux上で、スクリプト言語のインタープリタを実行することがありますが、この時、それらのインタープリタは単なるプロセスです。
こうした設計を、コンピュータ業界では「低レベルレイヤー」と「高レベルレイヤー」に分けて考えます。
ですが、単純に、Linuxカーネル上でPerlやPHPが動き、そのPerlやPHPを利用してそれぞれの掲示板やWebサービスのプログラムが動いていると考えると良いでしょう。
Linuxカーネルは、Cコンパイラであるgccなどでコンパイルされたバイナリであれば、Linuxカーネル上でそのまま動かせますが、JavaやPerlやPHPのような「間に抽象レイヤーが必要な言語」では、そのソフトウェア(ミドルウェア)を実行した上で、そのミドルウェアの上でプログラムが実行されます。最近ではC/C++でプログラムを作ることが次第に少なくなってきており、JavaやPythonなどのミドルウェアがLinuxでも良く使われています。
こうした「低レベル」「高レベル」は、言語以外に、X11のGUIシステムにも見られます。X11の上にGTKやQtの階層があり、その上でGNOMEやKDEが動き、その上でGUIアプリケーションが動きます。LinuxでGUIアプリケーションを使う時は、こうした抽象レイヤーの階層図を理解しておく必要があります。
システムレイヤーも参照のこと。
Linuxカーネルの特徴は、なんといってもその高パフォーマンス。商用のUNIXにも勝るほどの効率と性能で、プロセスやメモリを効率的かつ高速で処理する。また、安定性にも優れている。
FreeBSDなども高パフォーマンスであることで知られるが、Linuxカーネルの高パフォーマンスは、リーナスの高い技量と多くのコミュニティの人員が豊富であることが挙げられる。
だが、人員のスキルだけではなく、技術的に高度である。僕も分からないが、詳細を知りたい方は「詳解Linuxカーネル」に詳しいことが書いてある。Windowsなんか、サーバーには使えない。Linuxとは比較にならないほど、Windowsのレベルは低い。
Linuxは、リーナス・トーバルズが作っているカーネルがしっかりしているから、きちんと動く、ということが言えます。
どんなアプリケーションであれ、OSの上で動くプログラムは、全て、カーネルの上で動いています。
Linux上のシステムは、Apacheであれ、Perlであれ、GCCであれ、カーネルの上で動いています。
システムコールについては、カーネルでは基本的なものしか実装しておらず、多くがlibcなども介して動いています。Perlなどであれば、インタープリタの上で動いています。
ですが、Linuxカーネルがきちんとしているせいで、それらはとてもきちんと安定して動くのです。
Linuxは、マルチタスク・マルチユーザのOSをUNIXを模倣して作りましたが、ここで「UNIXを模倣した」というのがポイントです。リーナスは、単なるUNIXの再実装を開発しただけにすぎません。ですが、UNIXという巨大な遺産を継承したことで、簡単に「一流に動くもの」を作ることができたのです。
ですが、最近はWindowsも頑張っています。Windows NTのNTカーネルを再実装してから、Windowsはあまりフリーズせず、不安定でなくなりました。
なぜ、Windows 9xはそんなに不安定だったのでしょうか。
その理由は、Windowsという製品そのものが、MS-DOSをベースとしており、そのMS-DOSが、他社のCP/Mの互換OSを入手して改良した、「後付けの改良・改造を施したOS」だったからです。
他人が開発したソフトウェアを、別の人間が改造して、ウィンドウシステムのような巨大な機能を付け加えることは、とても難しいことです。Windows Meが不安定だったのは、それにマルチメディア機能などたくさんの機能を付け加えすぎたせいだと思います。
また、Windows 9xは一定の基準や標準が無く、Microsoftが独自に仕様を定めた結果、適当かついいかげんに仕様が膨らんでしまい、DOSのおかしなAPIと相まって、巨大で複雑なカーネルとなってしまったのです。
反面、Linuxカーネルは、リーナス・トーバルズが一から作ったカーネルを、ネット上のみんなで開発したOSです。リーナスが天才だっただけではなく、UNIXの優れたエンジニアが「自ら貢献しようという積極的な動機を持って改良」したのです。彼らは、素晴らしい仕事を「ネット上の協力」を通して行いました。リーナスが、「それが僕には楽しかったから」といったことを言ったのも、彼らとの協力そのものが楽しかったからであり、リーナスだけではなく、参加者が全員楽しかったのだと思います。
また、Linuxカーネルの上で動くコンパイラやコマンドツールはGNU Projectが開発していますが、彼らのソフトウェアは既にUNIXでの稼働実績があり、成熟していました。そこに、リーナスの作った高品質なカーネルが「上手く組み合わさった」ことで、GNUとLinuxは融和し、「一から作ろうとしては作れないところを、ネットの仲間やGNUやXFree86などの既製品と組み合わせて作り上げた」というOSがLinuxなのです。
リーナスは確かに偉大な天才ですが、誰にもできないことをしたわけではありません。
彼は、タネンバウム教授のMinix本を読んで、その通り、Minixを改良して、Minixと同じものを作りながら、Minixを改良したコードだけで動くようになり、最終的にインターネットに発表し、全てのMinixのコンポーネントをGNUのコンポーネントに置き換えて、独自の商用利用を禁じたライセンスはGPLに変更し、さまざまな人の改良パッチを取り入れただけだからです。
そういうわけで、タネンバウム教授のMinix本を読めば、きっとリーナスと同じことは誰でもできるでしょう。
そのMinix本が以下です。
MINIX本
僕も、そろそろMinix本を読むぐらいのレベルに来ているような気がします。家に第二版があるので、そのうち読もうと思っています。
ネットでは、Minix本はOSの仕組みを理解したい人というよりは、OSを作りたい人向けだと言います。
また、Minix本を書いたタネンバウム教授は、Linuxを「マイクロカーネルではなくモノリシックカーネルで、時代遅れだ」と言っています。現代的なカーネルはマイクロカーネルと呼ばれ、本当のカーネルは小さく、プロセス間通信と仮想CPU/仮想メモリの「最低限必要なものだけを実装したカーネル」とし、ファイルシステムやネットワークなどは、マイクロカーネル上の「サーバー」として実装し、いつでもそのサーバーをONにしたりOFFにしたりすることができるものであるべきですが、Linuxカーネルはそうしたカーネルに必要な機能をひとつのプログラムの中にいっしょくたにしています。これは初学者にとっては作りやすいカーネルですが、現代的なカーネルではありません。Linuxは今でもモノリシックカーネルを続けており、設計において技術的な新しい点もあまりなく、「普通のUNIX互換カーネル」でしかありません。
また、GNUから見ると、LinuxカーネルのおかげでGNU/Linuxシステムは完成しましたが、「GNUの全ての成果が、Linuxの成果であるかのように誤解されている」というところがあります。GNUのソフトウェアはフリーソフトウェアであるため、コピーや再配布が可能ですが、LinuxユーザーはGNUの成果をふんだんに取り入れながら、あたかもその全てをリーナス・トーバルズとコミュニティが開発したかのように人々に勘違いさせています。実際はリーナスやコミュニティはLinuxを開発しただけで、GNUまでは開発していません。GNUのストールマンは「GNU/Linuxと呼ぶべきだ」としていますが、Debianぐらいしかこの名称を本気で採用するプロジェクトはありません。そしてそのDebianすら、フリーソフトウェアでない「独占ソフトウェア」を含めて再配布しています。これはGNUから見てあってはならないことです。
そういうわけで、Linuxにはさまざまな課題や問題があり、またそのコミュニティも一様ではありませんが、そこが良いのです。みんなで開発し、みんなが別の理想を持って別の理由から開発したものを、共通の利益として共有していく、このプロジェクトの透明性と健全性こそが、オープンソースコミュニティの大原則です。最近は、Linuxカーネルでも、ボランティアの参加者は8%程度に過ぎず、多くが企業によって金銭的な利益を目的に開発されていますが、同時に、Mozilla.orgのように本当に金儲けではなく開発されているプロジェクトもあります。色んな人がいて、みんなで協力する姿勢は、とても良いものだと僕は思っています。Linuxは既に、昔のLinuxとは全く違うものですが、そうした考え方や理想そのものは変わっていないように感じます。
本当のところを言うと、GNUの言うように、リーナスやその仲間が開発した部分は本当に小さいものです。それは、UNIX由来のツールは、昔から作っていた人々が居て、たとえばviをビル・ジョイが開発したように、あるいはPerlをラリー・ウォールが、Rubyをまつもとゆきひろが開発したように、さまざまな人間が開発したものの寄せ集めに過ぎないからです。Red Hatなどが「保守と責任のサポートをやる」と言っていますが、彼らのやっていることは昔からUNIXの業者がやっていたこととあまり変わりません。そう、Linuxはまさに「コンピュータ技術を全部一緒にしたかのようなOS」です。そのため、Linuxをやっていると、本当にコンピュータの「歴史」が良く分かります。歴史的なさまざまなイディオムやプラクティスが多く、「ああ、これがまさにコンピュータだな」と感じられます。逆に、Windowsは新しいアーキテクチャ上の進歩が多く、Windowsを使っていると「新しい世界になったのだな」ということが良く分かります。新旧のWindowsとLinuxがともに進歩していけば、きっとIT技術の未来は明るいのではないかと思います。
2019.11.16追記:「詳解 Linuxカーネル」を読んでいて、この文章に少し誤りがあることに気付いた。すなわち、歴史上の伝統的なほとんどのUNIXカーネルはモノリシックだということ。Linuxはそれらと同様にモノリシックなカーネルでありながら、モジュール機構などを活用し、カーネルをフロッピーディスクに収めるぐらい小さくできる(少なくともこの本の第二版が出版された時点では)。よって、必ずしもマイクロカーネルの設計は必要ない。リーナスも開発者たちもそれを重々承知であると思う。
コンピュータは、CPUとメモリが、機械語で記述されたOSの膨大な情報を、ひらすらに計算する機械です。
ただひたすらに、機械語で書かれたOSの膨大な情報を計算します。これが「計算機」です。
Linuxカーネルがオープンソースであることは、「コンピュータを自由に使える」ということを意味しています。
プログラムのソースコードが公開されたLinuxカーネルでは、OSの内容を自分で研究したり書き換えたりすることができます。
カーネルだけではなく、GCCのようなツールチェイン(コンパイラや開発ツールの集合)がGPLでライセンスされているため、コンピュータの動作を自在に、どこまでも詳細に変更できます。
まさに、Linuxは「ハッキングのためのOS」であると言えます。
また、最近のIntel CPUの進歩は目覚ましく、数十年前のSunやHPなどのワークステーション以上の能力を、64bitのIntelプロセッサが持っています。これにLinuxを組み合わせることで、「現代版ワークステーション」を操作することができます。
Linuxカーネルの公式ドキュメントは以下にある。
以下は日本語に訳されているページ。
古いLinuxのドキュメントはthe Linux Documentation Projectにある。Linux JF (Japanese FAQ) Project.で翻訳がされているが、最近はあまり更新されていない。
以下はgitリポジトリの一覧。
以下はリーナス・トーバルズのリポジトリ。ソースコードツリーのブラウズもできる。
カーネル関連の文書は、LKMLのFAQにまとめられています。
特に、カーネルにパッチを投稿する場合は
[PATCH] cleanup of foo driver [1/5]
のようなサブジェクトをつける、といった決まりが書かれています。英語ですがカーネルハッカー候補生は必ず目を通しましょう。
以下に、初心者向けのLinuxカーネル開発者になるためのアドバイスがあり、参考になります。
Linuxカーネルハッカーのガイド。
Linuxカーネルの仕組み。日本語訳もあります。
Linuxカーネルモジュールのプログラミングガイド。モジュールを作るための定番のガイド。
Linuxカーネル2.4の仕組み。
フリーの電子書籍。カスタムLinuxカーネルを構築する方法が書かれている。プログラミングの内容ではない。
カーネルを管理するために、RHELの以下のガイドが参考になる。
RHELのドキュメントは基本的に参考になるのでいろいろと参照しても良いだろう。
以下はGentooとArchのカーネル関係のガイド。
Linuxカーネルの公式ドキュメント。
Linux関連の文書をまとめてある公式ドキュメント的なサイト。
カーネル関連の文書などを日本語訳している、準公式和訳的なサイト。
Linuxカーネルに追加された新機能や重要な修正などの概略を載せてくれている。
新しくカーネル開発者になりたい人はここから始めるべき。初心者レベルの質問に対して回答が返ってくることも多い。ただし英語。
タグ付けされたLinuxカーネルのコードをブラウズできる。
公式のWikiのリスト。
Linux Kernel開発者の集積ブログ。
OSDev WikiはOSの開発をする人に参考になるWikiです。
その他の情報源:
Linuxカーネル開発のための書籍の1つ。Amazonの評価は低いが、必ず読みなさい的な本であるようだ。
書籍の1つ。僕も買いましたが、読んでいません。
2019.11.16追記:今になってこの本を読んでいます。とても面白いです。
リーナス・トーバルズが読んだとされるタネンバウム先生のMINIXによる簡単なオペレーティングシステム理論の概要。
実践的で、自分でOSを作りたい人向き、ということらしい。もちろん難しい。
Linux Kernelのメーリングリストのアーカイブは以下を参照のこと。
書籍「Linuxカーネル2.6解読室」の一部が公開されています。
ネットにはさまざまな情報が溢れています。以下が参考になるかもしれません。
カーネルについて。
書籍
Linuxカーネルについて。
ソースコード
Linuxカーネルについては、git.kernel.orgからリポジトリの一覧を見ることができる。トーバルズの公式リポジトリはgit.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/にある。