スタンドアロン方式とリアルタイム性能:LinuxによるRTOSの実現(3)(2/3 ページ)
リアルタイム機能をLinuxカーネル自身で実現するスタンドアロン方式。この方式の具体的な実装やリアルタイム性能を検証する
プリエンプションの実現方法
このような状況下で少しでも理想に近づけようと、さまざまな取り組みが行われている。今回は以下の取り組みについて説明する。
- プリエンプティブル・カーネル(Preemptible Kernel)
- ボランタリ・カーネル・プリエンプション(Voluntary Kernel Preemption)
- リアルタイム・プリエンプション(Real-Time Preemption)
プリエンプティブル・カーネル
まず、2.6.0のリリース時にupstreamカーネルに追加されたプリエンプティブル・カーネルについて説明する。
カーネル2.4までは、カーネルの内部コードを実行している間は割り込みなどを契機にプリエンプションすることができなかった。この場合、カーネルの内部コードからユーザープログラムのコードに復帰する際に再スケジューリングが行われ、ほかのプロセス/スレッドに処理を切り替えた。
プリエンプティブル・カーネルとは、カーネルの内部コードにプリエンプションを行うポイントを設けて、ユーザープログラムのコードに戻る地点よりも早くに優先度の高い処理に切り替える試みである。
upstreamカーネルの2.6の実装では、割り込みから復帰する地点やスピンロックを解放する地点などがプリエンプション・ポイントとなっている。
ボランタリ・カーネル・プリエンプション
プリエンプティブル・カーネルにより、ある程度のレイテンシ改善は達成できる。しかし、前述したとおり、upstreamカーネルには長期間スピンロックを解放しない区間が存在する。この区間を細粒化するのが、ボランタリ・カーネル・プリエンプションの試みである。この機能は、2004年7月にIngo Molnar氏によりLinuxカーネル・メーリングリストに提案された。
具体的な実装では、クリティカルセクション中にすでに含まれているmight_sleep()というデバッグ用のマクロ関数をスケジューリング・ポイントとする。この関数が処理されて条件が満たされれば、スピンロックは破られて、優先度の高い処理へ切り替えられる。
Molnar氏は、upstreamカーネルにはないmight_sleep()の呼び出し個所を追加して、システム全体のレイテンシを低減した。これは、カーネル2.4に対して提案されたロー・レイテンシ・パッチ(Low Latency Patch)に相当するものである。
リアルタイム・プリエンプション
Molnar氏は、ボランタリ・カーネル・プリエンプションの実現にとどまらず、抜本的な見直しを継続した。その結果、2004年10月にリアルタイム・プリエンプションと銘打ったパッチ・セットをリリースした。これは、ボランタリ・カーネル・プリエンプションに以下のような機能を追加したものである。
- 割り込みハンドラのコードの大部分をカーネルスレッドにより実行する
- セマフォを用いてスピンロックを実現する
- セマフォに優先度継承機能を持たせる
- スピンロックによるクリティカルセクションを見直す
このうち、上の3つについてもう少し詳しく見てみよう。
割り込みハンドラのスレッド実行
割り込みハンドラは、カーネルが割り込みを受け付けると即座に動作する処理であり、プロセス/スレッドよりも優先して処理される。すなわち、割り込みハンドラの処理中は、プロセス/スレッドの実行は遅延させられる。
リアルタイムシステムでは、一部の割り込み処理よりも優先して実行したい処理もあるため、割り込みハンドラの処理にも何らかの優先度制御が必要となる。そこで、割り込みハンドラのコアとなる処理を、割り込み番号ごとに別々のスレッドで実行することにより優先度付けを行うアイデアが実装された。
セマフォによるスピンロックの実装
セマフォを用いてスピンロックを実装する利点は、スピンロックによるクリティカルセクション内でもプリエンプションが可能になることである。
この例では、割り込み発生後に、クリティカルセクションから抜けるのを待たずに別のプロセス/スレッド(ここではirqd)に切り替えることが可能になる。
優先度継承セマフォ
一般にいう優先度逆転現象も、セマフォに優先度継承機能を追加することで回避できる。優先度逆転現象の様子を図6に示す。
図6の場合、セマフォA(スピンロック)を優先度が低いプロセスAが保持していることから、優先度が最も高いプロセスBよりも、優先度が中程度のプロセスCが先に実行されてしまう。
優先度継承機能を追加することで、この現象が回避される様子が図7である。
プロセスBがセマフォAの獲得待ちでスリープする際、セマフォAを保持するプロセスAがプロセスBの優先度を継承することで、プロセスCよりも優先して処理される。結果、プロセスCよりも先にプロセスBが優先度どおりに実行される。
Copyright © ITmedia, Inc. All Rights Reserved.