web-dev-qa-db-ja.com

古いLinuxカーネルがプリエンプティブでない理由は何ですか?

最初のLinux開発者がノンプリエンプティブカーネルの実装を選択したのはなぜですか?同期を保存することですか?

私の知る限り、Linuxは90年代初頭にPCにシングルプロセッサが搭載されていたときに開発されました。非プリエンプティブカーネルは、このようなPCにどのような利点をもたらしますか?しかし、なぜマルチコアプロセッサによって利点が減少するのですか?

15
Narden

Linuxカーネルのコンテキストでは、ユーザーがプリエンプションについて話すとき、それ自体が割り込みを行うカーネルの機能を指します。本質的に、カーネルコードの実行中にタスクを切り替えます。これを可能にするのは非常に複雑です。おそらくこれが、カーネルがプリエンプティブルになるのに長い時間がかかった主な理由です。

大きなカーネルロックで保護されていたため、最初はほとんどのカーネルコードは中断できませんでした。そのロックは、ますます多くのカーネルコードから段階的に排除され、カーネルへの複数の同時呼び出しを並行して実行できるようになりました(これは、SMPシステムが一般的になるにつれて重要になった)。しかし、それでもカーネル自体をプリエンプティブルにすることはできませんでした。 thatはさらに開発を重ね、- PREEMPT_RT メインラインカーネルに最終的にマージされたパッチセット(とにかくBKLをプリエンプトできました)。現在、カーネルは、スループットとレイテンシ特性に応じて、多かれ少なかれプリエンプティブルになるように構成できます。詳細は 関連するカーネル構成 を参照してください。

カーネル構成の説明からわかるように、プリエンプションは同時実行性ではなくスループットと遅延に影響します。シングルCPUシステムでは、プリエンプションは、より短い反応時間でイベントを処理できるため、依然として有用です。ただし、スループットが低下します(カーネルがタスクの切り替えに時間を費やすため)。プリエンプションにより、単一または複数のCPUシステム内の任意のCPUが、より迅速に別のタスクに切り替えることができます。マルチCPUシステムの制限要因はプリエンプションではなく、それがロックであるか、大きいかどうかにかかわらずです。コードがロックを取得するたびに、別のCPUが同じアクションの実行を開始できないことを意味します。

26
Stephen Kitt

プリエンプティブカーネルは、 Big Kernel Lock がないことを意味します。

Linuxは最初の瞬間からプリエンプティブマルチタスクを実行していました(つまり、ユーザーコードはプリエンプティブでした)(私が知る限り、LinusがFunet FTPサーバーにアップロードした非常に最初のLinux 0.0.1はすでにプリエンプティブマルチタスクでした)。たとえば、複数の圧縮またはコンパイルプロセスを実行した場合、それらは最初から並行して実行されました。

逆に-当時-広く使用されているWin31。 Win31では、タスクが「カーネル」からCPUを取得した場合、デフォルトでは、いつOS(または他のタスク)に制御を戻すかを決定する責任がありました。プロセスにこの機能に対する特別なサポートがない場合(追加のプログラミング作業が必要)、それを実行している間、他のすべてのタスクが中断されました。 Win31に統合されたほとんどの基本的なアプリでさえ、そのように機能しました。

プリエンプティブマルチタスクとは、タスクに必要なCPUを割り当てる方法がないことを意味します。代わりに、それらの time slot が期限切れになると、カーネルはそれらからCPUを解放します。したがって、プリエンプティブオペレーティングシステムでは、正しく記述されていない、または正しく機能していないプロセスがOSを凍結したり、他のプロセスの実行を回避したりすることはできません。 Linuxは常にユーザー空間プロセスに先制的でした。

ビッグカーネルロックは、場合によってはカーネルスペース内にもロックが存在し、他のプロセスが保護されたコードを実行できないようにする可能性があることを意味します。たとえば、 mount 複数のファイルシステムを同時に実行することはできません。複数のマウントコマンドを指定した場合、Big Kernel Lockを割り当てるためにマウントする必要があるため、それらのコマンドは引き続き連続して実行されました。

カーネルをプリエンプティブにするには、この大きなカーネルロックを排除する必要がありました。つまり、マウントと他のタスクを同時に実行できるようにする必要があります。大変な仕事でした。

歴史的に、これはSMP(マルチCPUサポート)のサポートの増加によって非常に緊急に行われました。初めて、本当にマルチCPUのメインボードがありました。その後、複数のCPU(「コア」)が単一のチップに統合されましたが、今日、本当にマルチCPUのメインボードはすでに珍しいものです(通常、高価なサーバーシステムに搭載されています)。また、本当にシングルコアシステム(CPUが1つだけで、コアが1つだけのシステム)はまれです。

したがって、あなたの質問への答えは、「プリエンプティブでない理由は何か」ではありません。なぜなら、それは常にプリエンプティブだったからです。本当の問題は、プリエンプティブカーネルの実行が本当に必要になった理由です。答えはそのためです:メニーCPU、メニーコアシステムの比率の増加。

これは技術的な答えではありませんが、OPによって提起された特定の質問に対する歴史的な答えです。「古いLinuxカーネルの非優先性の理由は何でしたか?」

(私は、@ peterhが彼の回答とコメントで説明したように、「非プリエンプティブ」とは、OPがカーネル内(API内)で1つのユーザープロセスしか存在できないという事実のいずれかまたは両方を指していると思います時間および/またはビッグカーネルロック。)

Linus Torvaldsは、オペレーティングシステムがどのように機能するかを学ぶことに興味があり、彼が学んだ方法はオペレーティングシステムを記述することでした。彼のモデル、ベース、および初期開発環境はMinixでした。これは教育目的の既存のOS(つまり、本番OSではありません)であり、(オープンソースのように)当時は無料ではありませんでした。ビールのように無料ではありませんでした。どちらか)。

したがって、彼はプリエンプションのないカーネル(他の回答で言及されているビッグカーネルロック)を書いたので、これは、教育目的で新しいOSをすばやく稼働させたい場合に行う方法です。その方法は、はるかに単純です。ユーザープログラムとデバイスの同時マルチプログラミングをサポートするカーネルは十分に困難です-それは極端にカーネル自体を並列にすることは困難です。

彼がLinuxがどれほど人気が​​あり、便利で、重要なものになるかを知っていたとしたら、おそらく同じようにしていたでしょう。 (IMOのみ、私は彼が実際に何を考えているのかわかりません。)走る前に歩く必要があるからです。

そして、a)今日のLinux(または当時のLinux)を作成するために他にも多くの作業が必要であり、b)変更するのは非常に困難な作業であるため、長い間このままでした。 (他の回答で説明されているように)。

3
davidbak