Linuxカーネル2.5 最新開発動向
2002/4/9
カーネル2.5に取り込まれた機能と改良点
■ブロックI/Oキューの改良
開発版カーネル2.5で最初の大きな変更となったのが、Jens Axboe氏によるブロックI/Oキューの改良である。
カーネル2.4まで、ブロックI/O(ディスクI/O)への処理要求をためておくキューはio_request_lockと呼ばれる1つの大きなスピンロック(BKL:Big Kernel Lock)によって保護していた。この方法では、ブロックI/O処理を行うといつでもロックされてしまうため、ほかのブロックI/O処理はロックが外れるまで待たなければならず、スケーラビリティを十分に伸ばすことができない。
また、アプリケーションから発行された大きなブロックI/O要求を、カーネル内部でいったん個々の小さなブロック単位に分割し、再びエレベータアルゴリズムと呼ばれる部分で統合するという無駄な処理も行われていた。
Axboe氏は、ブロックI/Oの処理からSCSIデバイスドライバに至るまで改良を加え、新たに「bio構造体」というデータ構造を導入した。これにより、ブロックI/Oキューのロックを各要求キューにかけられるようになり、デバイスごとに並列にブロックI/O処理できるようになった。さらに、小さなブロックに分割するといった無駄な処理を省くことが可能になった。
また、1Gbytes以上のメモリ(HIGHMEM)を使用するシステムでは、I/Oを行う際に、データをバウンスバッファと呼ばれるメモリ領域に1度コピーする必要があったが、そのコピーをなくす改良も同時に取り込まれた。
ブロックI/Oキューの改良に関するより詳細な情報は、
http://lse.sourceforge.net/io/bionotes.txt
Suparna Bhattacharya氏による"Notes on 2.5 block i/o layer changes"
http://www.uwsg.iu.edu/hypermail/linux/kernel/0111.3/1187.html
Axboe氏がカーネルメーリングリストに投稿したメール
で参照可能である。
■スケジューラとランキューの改良
Linuxは、1つのCPU上で複数のプロセスを動作させるマルチタスクOSである。マルチタスクは、短時間に複数のプロセスを時分割して切り替えて(これをスケジューリングと呼ぶ)動作させることで実現している。そのスケジューリングを制御するのが「スケジューラ」と呼ばれる部分である。
図1 従来のスケジューラ。SMP環境ではランキューがボトルネックになる |
Linuxでは、カーネル2.4までの長い間、システム全体で1つのランキュー(走行可能なプロセスのキュー)だけを用いてスケジューリングを行うという、非常にシンプルなスケジューラが使用されてきた。この方式は、実装がシンプルにできる半面、プロセスをスケジューリングさせるたびにランキューを線形検索しなければならない。そのため、多数のプロセスが動作するようなエンタープライズクラスの大規模システムでは、プロセス数の分だけスケジューラの処理時間がかかってしまうという問題があった(図1)。
また、複数のプロセッサを持つシステムでは、プロセスがCPU間で不定に割り当てられてしまう(プロセスがCPU間を動き回る)ためにキャッシュ利用効率が悪化する。さらに、複数のCPUで共有するランキューを制御するときにかけるロックが原因で、十分なスケーラビリティが得られないことなどの問題も存在していた。
この問題を解決しようとしたのが、Ingo Molnar氏による「O(1)スケジューラ」である。O(1)スケジューラは、以下の3点を目的に設計された。
- スケジューラのオーバヘッドを減らす
- プロセッサ間でプロセスが移動しないようにする
- 負荷にかかわらず良い性能を保つ
図2 O(1)スケジューラにおけるランキューの構造。ランキューはプロセスへのポインタの配列であり、優先度でソートされている |
オーバヘッドを減らすという点からは、プロセス優先度でソートされたプロセスキューの配列でランキューを実装し、優先度の高いプロセスから動作させる構造に変更した(図2)。ビットマップなどを介してランキューを参照すると、次に動かすべきプロセスがすぐ分かることから、O(1)(オーダーが1)スケジューラという名前が付けられた。
また、ランキューは「active」と「expired」という2つのキューから構成されている(図3)。動作させるプロセスは、常にactiveキューから選択される。別のプロセスに切り替えるときは、現在のプロセスをactiveキューからexpiredキューに移し、次のプロセスをactiveキューから選ぶ。すべてのプロセスがexpiredキューに移動し、activeキューが空になった段階でactiveキューとexpiredキューの役割をひっくり返し、再びactiveキューからプロセスを選択してスケジューリングを行う。
図3 O(1)スケジューラ。CPUごとにキューを持ち、切り替えられたプロセスはexpiredキューに移される。activeキューが空になると、2つのキューの役割を交代させる。active/expired両キューは、それぞれ図2のような構造になっている |
CPUごとにキューを持つようになったのも大きな特徴である。キューをCPUごとに持つことで、CPU間でプロセスが移動しにくくなった。また、スケジューラがCPUごとに動作することでランキューに対するロック競合をなくし、スケーラビリティを格段に向上させることができるようになった。
リアルタイムプロセスでは、遅延を最小限に抑える工夫が必須である。そこで、リアルタイムプロセスに対しては、システム全体で単一のランキューをactive/expiredキューとは別に用意しておく。リアルタイムプロセスを動作させたいときは、リアルタイムプロセス用のランキューからプロセスを選択し、全CPUの中からなるべく空いているCPU上で動かすことで、遅延の最小化を図っている。
O(1)スケジューラに対してはさまざまなベンチマークが取られており、いずれの結果からも大きく性能が伸びることが示されている。Molnar氏が取ったベンチマーク結果では、スケジューラの性能が通常の単一CPUシステムでも数十%、SMPシステムでは最大600%近い伸びを示すなど、大きな成功を収めている。
O(1)スケジューラについてより詳しく知りたいのであれば、
http://www.uwsg.iu.edu/hypermail/linux/kernel/0201.0/0810.html
Molnar氏がカーネルメーリングリストに投稿したメール
が参考になるだろう。
■プリエンプティブルカーネルサポート
LinuxがマルチタスクOSであることは、すでにスケジューラの解説で述べた。各プロセスには動作可能な時間(クオンタム)が与えられており、この時間が過ぎると強制的に別のプロセスに切り替えられる。割り込みやクオンタムが過ぎたことを契機として、プロセスがスケジューリングされることを「プリエンプション」と呼ぶ。
UNIX系のOSでは、通常プリエンプションが発生するのはユーザープログラムを実行中のときのみである。システムコール実行中など、カーネル内部の処理を行っているときは、明示的にカーネル内で指定しない限りプロセスのスケジューリングは発生しない。通常の用途では、この仕組みで不都合なく十分動作する。
しかし、ディスクアクセスを行いながら同時に音楽を再生するなどしたらどうなるだろうか。音楽を再生するときは、通常アプリケーションからオーディオバッファへ数ミリ〜数十ミリ秒間隔でデータを転送し、オーディオバッファにためられたデータが順次再生されていく。だが、次の音をバッファに転送しなければならない状態であるにもかかわらず、ディスクアクセスなど、場合によっては数十ミリ秒程度の遅延時間がかかるシステムコールを処理してしまうと、その処理時間にCPUが引きずられる。もし、その間にためられた音楽が全部再生され、オーディオバッファが空になると音が途切れてしまうのだ。これでは、ディスクアクセス処理を行いながらの音楽同時再生は聴きづらいものになってしまうことが分かるだろう。
そこで、カーネル内部の処理を行っている最中でも、プリエンプションを許可することで、音の途切れを極力抑えることを可能とするのが、Nigel Gamble、Robert Love氏らによる「プリエンプティブルカーネル」である。
通常、カーネルは内部でプリエンプションが発生することを考慮してプログラムされていない。しかし、プリエンプティブルカーネルはマルチプロセッサを使用するときに必須な「スピンロック」と呼ばれる仕組みに目を付け、スピンロックを実行している間以外はカーネル内部でもプリエンプション可能とすることに成功している。
この機能は2.5.4-pre6以降のカーネルで使用できる。プリエンプティブルカーネルを利用することで、リアルタイム性を必要とするようなマルチメディア処理などで、遅延を最小限に抑えることが可能になっている。リアルタイム性に興味があるユーザーにとっては、試す価値のある機能ではないだろうか。
プリエンプティブルカーネルについては、
http://kpreempt.sourceforge.net/
The Linux kernel preemption project
からたどることができる。
■kdev_t型の拡張によるデバイス管理機能の強化
2002年の開発版カーネル2.5は、前述のO(1)スケジューラとLinus氏によるkdev_t改良で幕が開けた。
このkdev_t改良に触れる前に、コンピュータに接続されたデバイスがLinuxでどのように表現されているかについて解説しよう。Linuxに限らずUNIXでは、デバイスを「デバイスファイル」と呼ばれる特殊なファイルで表現する。「/dev/hda」は、「1番目のIDEハードディスクを示す」などがその一例である。この/dev/hdaという名前は、あくまでもユーザーに分かりやすいよう便宜上付けられた名前であり、Linuxカーネルの内部では「デバイス番号」というものでデバイスを管理している。例えば、/dev/hdaをlsで見ると、
$ ls -al /dev/hda |
と表示される。「3, 0」と示されているのが/dev/hdaというファイルに割り当てられたデバイス番号である。上記の例だと、「3」の部分をメジャー番号(3はIDEを表すデバイス種別)、「0」の部分をマイナー番号(0は1番目のIDEデバイス)と呼ぶ。
カーネル2.4までは、上位8bitsをメジャー番号、下位8bitsをマイナー番号に割り当て、全体でデバイス番号を16bits(65536個)の値としていた。しかし、近年の大規模システムでは、16bitsで表現できるデバイス数では足りない可能性が出てきた。そこで、Linus氏はカーネル内部のデバイス番号を表現するkdev_t型を32bitsに拡張し、上位12bitsをメジャー番号、下位20bitsをマイナー番号に割り当てるように変更した。同時に、多くのドライバの内部で使用されていたdev_t型をkdev_t型へ移行するという作業が行われた。
とりわけ数千台以上のデバイスを同時に扱う必要のあるエンタープライズ分野などにおいて、Linuxの利用可能性をさらに広げる変更だったといえるだろう。
■JFSの正式取り込み
|
開発版カーネル2.5では、ファイルシステムにも多数の改良が加えられている。その一例として、BKLの削除やプロセスごとの名前空間設定、JFSの取り込みなどが挙げられる。この中から、JFSについて紹介しよう。
JFS(Journaled File System)は、IBMが開発しているジャーナリングファイルシステムである。もともと、JFSはAIXやOS/2などで稼働していたが、Linuxにも移植が行われている。
Linuxで代表的なジャーナリングファイルシステムとしてReiserFS、ext3、JFS、XFSの4種類が挙げられる。カーネル2.4でReiserFS、ext3が取り込まれていたが、JFSも2.5.6-pre2でようやくカーネルに入った。
JFSについての詳しい情報は、
http://oss.software.ibm.com/developerworks/oss/jfs/
より取得できる。なお、安定版カーネル2.4用のパッチもこのサイトで入手できる。
■新アーキテクチャへの対応
開発版カーネル2.5では、新たにx86_64とppc64という2つのアーキテクチャがカーネルに取り込まれた。x86_64は、AMDのx86-64(Hammer)と呼ばれる64bit CPUをサポートするものである。ppc64は、IBM Powerシリーズなどで使用されている64bit版PowerPC向けアーキテクチャをサポートする。
興味深い点として、AMD x86-64は実際にはまだ販売されていないCPUであるにもかかわらず、Linuxカーネルに取り込まれたことである。AMDは、将来的にx86-64が販売されたときすぐ使用可能な状態にしておこうとする同社の方針に基づき、Linux、FreeBSD、NetBSDなどに対して積極的にポーティング情報を提供しているためだ。
x86-64については、
http://www.x86-64.org/
ppc64については、
http://linuxppc64.org/
で、それぞれ情報を入手できる。
■ALSAの取り込み
ALSA(Advanced Linux Sound Architecture)は、Jaroslav Kysela氏を中心としたALSA開発チームによってまったく新規に作られたLinux用サウンドシステムである。
カーネル2.4までのサウンドシステムは、OSS(Open Sound System)と呼ばれるドライバをベースにしたものが使用されていた。それに対し、ALSAは既存のOSSインターフェイスと互換性を維持しながらも、デバイスサポートやモジュール化、ライブラリ/APIの整備など、OSSに不十分であったさまざまな新しい機能を追加している。
ALSAは、長年ALSA Projectより配布されており、カーネル2.4までには含まれていなかった。しかし、最近はALSAのサウンドカードサポートが充実してきたこともあり、いくつかのディストリビューションではALSAが使用可能になっている。そして、開発版カーネルでもついに2.5.5-pre1でALSAが取り込まれた。最新の開発版カーネルソースのトップディレクトリを見ると、「sound」というディレクトリを確認することができるだろう。もちろん、ALSAだけでなくOSSのサウンドドライバも依然として利用可能になっている。
ALSAについての情報は、
http://www.alsa-project.org/
で参照可能である。
カーネル動向を追いかけるなら
以上、開発版カーネル2.5の概要を駆け足でお伝えしたが、いかがであっただろうか。
本記事では、とりわけ開発版カーネルに加えられた主要な変更をピックアップして紹介したが、ほかにも実に多くの改良が日々加えられている。ここまで紹介した機能も含め、開発版カーネル2.5の新機能の開発進捗状況は、Guillaume Boissiere氏がメンテナンスする以下のURLで確認できる。
http://kernelnewbies.org/status/latest.html
Kernel 2.5 status
このWebページは、最近行われた大きな変更点も常時反映しているので、最新動向や今後何が開発されるのかチェックするのに参考となるだろう。
開発版カーネル2.5は、「開発版」と位置付けられているだけあって、十分テストされていなかったり安定性を欠いていたりするため、不用意にサーバなどで動かさない方がよい。しかし、それでもカーネル2.5の新機能に興味を持たれた方は、ぜひその目で確かめてみてほしい。最新のLinuxカーネルに取り込まれたさまざまな機能を一足先に満喫できるに違いない。
2/2
|
|
|
||||
|
Linux Square全記事インデックス |
Linux Squareフォーラム Linuxカーネル関連記事 |
連載:Linux Kernel Watch(連載中) Linuxカーネル開発の現場ではさまざまな提案や議論が交わされています。その中からいくつかのトピックをピックアップしてお伝えします |
|
連載:Linuxファイルシステム技術解説 ファイルシステムにはそれぞれ特性がある。本連載では、基礎技術から各ファイルシステムの特徴、パフォーマンスを検証する |
|
特集:全貌を現したLinuxカーネル2.6[第1章] エンタープライズ向けに刷新されたカーネル・コア ついに全貌が明らかになったカーネル2.6。6月に正式リリースされる予定の次期安定版カーネルの改良点や新機能を詳しく解説する |
|
特集:/procによるLinuxチューニング[前編] /procで理解するOSの状態 Linuxの状態確認や挙動の変更で重要なのが/procファイルシステムである。/procの概念や/procを利用したOSの状態確認方法を解説する |
|
特集:仮想OS「User
Mode Linux」活用法 Linux上で仮想的なLinuxを動かすUMLの仕組みからインストール/管理方法やIPv6などに対応させるカーネル構築までを徹底解説 |
|
Linuxのカーネルメンテナは柔軟なシステム カーネルメンテナが語るコミュニティとIA-64 Linux IA-64 LinuxのカーネルメンテナであるBjorn Helgaas氏。同氏にLinuxカーネルの開発体制などについて伺った |
|
|
- 【 pidof 】コマンド――コマンド名からプロセスIDを探す (2017/7/27)
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、コマンド名からプロセスIDを探す「pidof」コマンドです。 - Linuxの「ジョブコントロール」をマスターしよう (2017/7/21)
今回は、コマンドライン環境でのジョブコントロールを試してみましょう。X環境を持たないサーバ管理やリモート接続時に役立つ操作です - 【 pidstat 】コマンド――プロセスのリソース使用量を表示する (2017/7/21)
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、プロセスごとのCPUの使用率やI/Oデバイスの使用状況を表示する「pidstat」コマンドです。 - 【 iostat 】コマンド――I/Oデバイスの使用状況を表示する (2017/7/20)
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、I/Oデバイスの使用状況を表示する「iostat」コマンドです。
|
|