Linuxカーネルはプリエンプティブであり、ほとんどのUnixカーネルとは異なります。では、カーネルがプリエンプティブであるとはどういう意味ですか?
いくつかの類推や例は、純粋な理論的説明よりも優れています。
プリエンプティブ はマルチタスクのパラダイムの1つにすぎません。 協調マルチタスク のような他のものがあります。それらを比較することで、より良い理解を得ることができます。
プリエンプティブマルチタスクの単純なビューを想像してみてください。 2つのユーザータスクがあり、どちらもI/Oを使用したりカーネル呼び出しを実行したりせずに常に実行されています。これらの2つのタスクは、マルチタスクオペレーティングシステムで実行できるようにするために特別なことをする必要はありません。カーネルは、通常はタイマー割り込みに基づいており、あるタスクを一時停止して別のタスクを実行する時間であると判断するだけです。問題のタスクは、何かが起こったことを完全に認識していません。
ただし、ほとんどのタスクは、syscallを介してカーネルに時折要求を行います。これが発生すると、同じユーザーコンテキストが存在しますが、CPUはそのタスクに代わってカーネルコードを実行しています。
古いLinuxカーネルは、カーネルコードの実行でビジー状態のときに、タスクのプリエンプションを許可しませんでした。 (I/O操作は常に自発的に再スケジュールされることに注意してください。カーネルコードにリストの並べ替えなどのCPUを集中的に使用する操作がある場合について話しています。)
システムがそのタスクのプリエンプションを許可している場合カーネルコードの実行中「プリエンプティブカーネル」と呼ばれるものがあります。このようなシステムは、システムコール中に発生する可能性のある予測できない遅延の影響を受けないため、組み込みタスクまたはリアルタイムタスクに適している可能性があります。
たとえば、特定のCPUで2つのタスクを使用でき、1つは完了までに5ミリ秒かかるシステムコールを受け取り、もう1つは2ミリ秒ごとにオーディオパイプにフィードする必要があるMP3プレーヤーアプリケーションである場合、音声が途切れる可能性があります。
プリエンプションに反対する議論は、タスクコンテキストで呼び出される可能性のあるすべてのカーネルコードがプリエンプションを乗り切ることができなければならないということです-たとえば、以前に操作を常に完了できる場合は、より良いデバイスドライバーコードがたくさんありますそのプロセッサで他のタスクを実行できるようにします。 (最近の例外ではなくマルチプロセッサシステムのルールでは、すべてのカーネルコードを再入可能にする必要があるため、今日の議論はそれほど重要ではありません。)さらに、syscallを改善することで同じ目標を達成できる場合は、待ち時間、おそらくプリエンプションは不要です。
妥協案はCONFIG_PREEMPT_VOLUNTARYです。これにより、カーネル内の特定のポイントでタスク切り替えが可能になりますが、どこでも可能になるわけではありません。カーネルコードが行き詰まる可能性のある場所が少ない場合、これは複雑さを管理しやすくしながらレイテンシーを削減する安価な方法です。
Linuxカーネルバージョン2.5.4より前は、Linuxカーネルはプリエンプティブではありませんでした。つまり、カーネルモードで実行されているプロセスは、それ自体がプロセッサを離れるか、入出力操作が完了するのを待ち始めるまで、プロセッサから移動できません。
通常、ユーザーモードのプロセスは、システムコールを使用してカーネルモードに入ることができます。以前は、カーネルがプリエンプティブではなかった場合、優先度の低いプロセスは、システムコールを繰り返し呼び出してカーネルモードを維持することにより、プロセッサへのアクセスを拒否することにより、優先度の高いプロセスを反転させることができました。優先度の低いプロセスのタイムスライスが期限切れになった場合でも、カーネルでの作業が完了するか、自発的に制御を放棄するまで、プロセスは実行を継続します。実行を待機している優先度の高いプロセスが、ユーザーが入力しているテキストエディター、またはオーディオバッファーを補充する準備ができているMP3プレーヤーである場合、インタラクティブなパフォーマンスが低下します。このように、非プリエンプティブカーネルは当時の大きな欠点でした。
従来のUNIXカーネルには単一のロックがあり、カーネルコードの実行中にスレッドによって保持されていました。したがって、他のカーネルコードがそのスレッドに割り込むことはできません。
これにより、1つのスレッドがカーネルリソースを使用しているのに、他のスレッドは使用していないことがわかっているため、カーネルの設計が容易になりました。したがって、異なるスレッドがお互いの作業を台無しにすることはできません。
シングルプロセッサシステムでは、これはそれほど多くの問題を引き起こしません。
ただし、マルチプロセッサシステムでは、異なるプロセッサまたはコア上の複数のスレッドがすべてカーネルコードを同時に実行したいという状況が発生する可能性があります。つまり、ワークロードのタイプによっては、多数のプロセッサが存在する可能性がありますが、それらはすべて、ほとんどの時間を互いに待機することに費やしています。
Linux 2.6では、カーネルリソースがはるかに小さな単位に分割され、個々のロックによって保護され、対応するリソースが使用されている間だけロックが保持されるようにカーネルコードがレビューされました。そのため、異なるプロセッサは、同じリソース(ハードウェアリソースなど)にアクセスする場合にのみ、互いに待機する必要があります。
プリエンプションにより、カーネルは並列処理の印象を与えることができます。プロセッサは1つしかありませんが(たとえば10年前)、すべてのプロセスが同時に実行されているように感じます。これは、カーネルが1つのプロセスからの実行をプリエンプト(つまり、実行を削除)して、次のプロセスに渡すためです(おそらく優先順位に従って)。
[〜#〜] edit [〜#〜]プリエンプティブではないカーネルはプロセスが手を返すのを待ちます(つまり、システムコール中)。したがって、プロセスが大量のデータを計算し、どのような種類のyield
関数も呼び出さない場合、他のプロセスは実行して呼び出しを実行できません。このようなシステムは、実行時間の公平性を確保するためにプロセスの協力を求めるため、協力的と呼ばれます。
EDIT 2プリエンプションの主な目標は、複数のタスク間のシステムの反応性を向上させることです。これは、エンドユーザーにとっては良いことですが、他の場合は一方、サーバーは最高のスループットを達成したいので、それは必要ありません:( Linuxカーネル構成から)
これは、オペレーティングシステムのスケジューラーが実行中のプロセスの実行を自由に中断して、CPUを別のプロセスにいつでも提供できることを意味します。これを行う通常の方法は、CPUを待機している各プロセスにCPU時間の「クォンタム」の実行を与えることです。有効期限が切れると、スケジューラーは制御を取り戻し(実行中のプロセスはこれを回避できません)、別のクォンタムを別のプロセスに渡します。
この方法は、プロセスが中断されることなく必要な時間だけCPUを保持し、他のアプリケーションを実行させるために何らかの「yield」関数を明示的に呼び出す必要がある協調マルチタスクとよく比較されます。当然のことながら、システムがスタックしているような感覚を与えることを避けるために、正常に動作するアプリケーションはCPUを頻繁に生成します。それでも、アプリケーションにバグがある場合(たとえば、yield呼び出しのない無限ループ)、CPUは障害のあるプログラムによって完全に保持されているため、システム全体がハングします。
最近のほとんどすべてのデスクトップOSはプリエンプティブマルチタスクを使用しており、リソースの点でより高価であっても、一般的に安定しています(OSは常に制御されているため、単一の障害のあるアプリがシステム全体をハングさせるのはより困難です)。一方、リソースが不足していて、アプリケーションが正常に動作することが期待される場合は、協調マルチタスクが使用されます。 Windows3は協調マルチタスクOSでした。より最近の例は、オープンソースのPMPファームウェアの代替品であるRockBoxです。
Linuxカーネルはモノリシックであり、実行中のすべてのプロセスに少しずつ計算時間を与えます。これは、プロセス(プログラムなど)が同時に実行されないことを意味しますが、ロジックを実行するために定期的に一定の期間が与えられます。主な問題は、一部のロジックの終了に時間がかかり、カーネルが次のプロセスに時間をかけることができないことです。これにより、システムに「遅れ」が生じます。
優先カーネルには、 コンテキストの切り替え を実行する機能があります。これは、終了していなくても「ハング」プロセスを停止し、期待どおりに次のプロセスに計算時間を与えることができることを意味します。 「ハング」プロセスは、問題なく実行されます。
実際には、カーネルにはリアルタイムでタスクを実行する機能があることを意味します。これは、オーディオの録音と編集にとって特に興味深いものです。
buntu studio districution は、プリエンプティブカーネルと、オーディオおよびビデオエディション専用の高品質のフリーソフトウェアをパッケージ化しています。
誰もがこれをうまく説明できたと思いますが、もう少し情報を追加します。 Linux IRQ、割り込み、カーネルスケジューラのコンテキストで。
プロセススケジューラは、現在実行中のジョブ/プロセスを実行し続けるかどうか、実行しない場合は次に実行するプロセスを決定するOSのコンポーネントです。
プリエンプティブスケジューラは、割り込みを許可し、実行中のプロセスがその状態を変更してから、別のプロセスを実行できるようにするスケジューラです(現在のプロセスは中断)。
一方、非プリエンプティブスケジューラーは、プロセスからCPUを奪うことはできません(別名協調)FYI、 Wordの「cooperative」という名前は、Wordの意味がスケジューラーが実際に行うことを明確に示していないため、混乱を招く可能性があります。
たとえば、3.1のような古いWindowsには協調スケジューラがありました。
素晴らしいへの完全なクレジット ここの記事
Linuxカーネルがプリエンプティブであるということは、カーネルがプリエンプションをサポートしていることを意味します。
たとえば、読み取りシステムコールを実行している2つのプロセスP1(高い優先度)とP2(低い優先度)があり、それらはカーネルモードで実行されています。 P2が実行中であり、カーネルモードであり、P2の実行がスケジュールされているとします。
カーネルプリエンプションが使用可能な場合、プリエンプションはカーネルレベルで発生する可能性があります。つまり、P2はプリエンプションされる可能性がありますが、スリープ状態になり、P1は実行を継続できます。
P2はカーネルモードであるため、カーネルプリエンプションが使用できない場合、システムはP2が完了するまで待機してから
2.6からプリエンプティブになったと思います。プリエンプティブとは、新しいプロセスを実行する準備ができたときに、CPUが新しいプロセスに割り当てられることを意味します。実行中のプロセスが協調的であり、CPUを放棄する必要はありません。