11

一見すると、私の質問は些細なことに見えるかもしれません。私と一緒に我慢して、完全に読んでください。

Linux カーネル モジュールでビジー ループを特定しました。このため、他のプロセス (sshd など) は長時間 (20 秒など) の間 CPU 時間を取得していません。私のマシンには単一の CPU しかなく、ビジー ループが他のプロセスをスケジュールする機会を与えていないため、これは理解できます。

実験のために、ビジー ループの各反復の後に schedule() を追加しました。これは CPU をビジー状態に保ちますが、schedule() を呼び出しているため、他のプロセスを実行できるはずです。しかし、これは起こっていないようです。ユーザー レベルのプロセスがまだ長時間 (20 秒) ハングしています。

この場合、カーネル スレッドはナイス値 -5 を取得し、ユーザー レベル スレッドはナイス値 0 を取得しました。ユーザー レベル スレッドの優先度が低くても、20 秒は長すぎて CPU を取得できないと思います。

誰かがなぜこれが起こっているのか説明できますか?

注: ビジー ループを完全に削除する方法を知っています。ただし、ここでカーネルの動作を理解したいと思います。カーネル バージョンは 2.6.18 で、カーネル プリエンプションは無効になっています。

4

1 に答える 1

2

このschedule()関数は単にスケジューラーを呼び出すだけです。呼び出し元のスレッドが別のスレッドに置き換えられるように調整するための特別な手段はありません。現在のスレッドが実行キューで最も優先度の高いスレッドである場合は、スケジューラーによって再度選択されます。

カーネルスレッドがビジーループでほとんど作業を行っておらず、schedule()毎回呼び出しているように聞こえます。したがって、CPU時間自体をあまり使用していないため、優先度が大幅に低下することはありません。負のナイス値は正の値よりも重みが大きいため、-5と0の違いは非常に顕著です。これらの2つの効果の組み合わせは、ユーザースペースプロセスが見逃していることにそれほど驚かないことを意味します。

実験として、ループのN回目の反復ごとにスケジューラーを呼び出して(プラットフォームに適したNの値を見つけるために実験する必要があります)、状況が良いかどうかを確認schedule()できます。頻繁に呼び出すと、多くのCPUが無駄になります。スケジューラーの時間。もちろん、これは単なる実験です-すでに指摘したように、ビジーループを回避することは本番コードの正しいオプションです。スレッドが別のスレッドに置き換えられていることを確認したい場合は、リモート自体TASK_INTERRUPTIBLEを呼び出す前にスレッドを設定してくださいschedule()実行キューから(コメントですでに述べたように)。

カーネル(2.6.18)は、2.6.23でCompletely Fair Schedulerが追加されるまで存在していたO(1)スケジューラーを使用していることに注意してください(O(1)スケジューラーは2.6で追加され、さらに古いO(n )スケジューラ)。CFSは実行キューを使用せず、異なる方法で動作するため、異なる動作が見られる可能性があります。ただし、私はあまり詳しくないので、どのような違いが見られるかを正確に予測したくありません。「完全に公平」とは、コアとプロセスの両方が多数ある高負荷のSMPシステムで使用する用語ではないことを十分に理解していますが、スケジューラーの作成は非常に難しいことも認めています。タスクとそれは私が見た中で最悪とはほど遠いです、そして私は」

于 2013-02-01T01:34:48.723 に答える