Linuxカーネルのスケジュールプロセスが実際にどのように機能するかを理解しようとしています。私の質問は、スケジューリングアルゴリズムについてではありません。関数schedule()
とswitch_to()
がどのように機能するかについてです。
説明しようと思います。私はそれを観た:
プロセスがタイムスライスを使い果たすと、フラグ_need_resched
_がscheduler_tick()
によって設定されます。カーネルはフラグをチェックし、フラグが設定されていることを確認し、schedule()
(質問1に関連)を呼び出して新しいプロセスに切り替えます。このフラグは、別のプロセスを実行する価値があるため、スケジュールをできるだけ早く呼び出す必要があるというメッセージです。ユーザースペースに戻るか、割り込みから戻ると、_need_resched
_フラグがチェックされます。設定されている場合、カーネルは続行する前にスケジューラーを呼び出します。
カーネルソース(linux-2.6.10-「Linuxカーネル開発、第2版」の本が基づいているバージョン)を調べると、一部のコードがschedule()
関数を自発的に呼び出して、別のコードを与えることができることもわかりました。実行する権利を処理します。関数switch_to()
が実際にコンテキストスイッチを実行する関数であることがわかりました。 switch_to()
が実際に何をしているかを理解しようとして、アーキテクチャに依存するコードをいくつか調べました。
その振る舞いは私が答えを見つけることができなかったいくつかの質問を引き起こしました:
switch_to()
が終了すると、現在実行中のプロセスは何ですか? schedule()
を呼び出したプロセス?または、次のプロセス、実行するために選択されたプロセスですか?
schedule()
が割り込みによって呼び出されると、実行するために選択されたプロセスは、割り込み処理が終了したときに実行を開始します(ある種のRTEの後)?またはその前に?
割り込みからschedule()
関数を呼び出せない場合、フラグ-_need_resched
_はいつ設定されますか?
タイマー割り込みハンドラーが機能しているとき、どのスタックが使用されていますか?
はっきりさせることができるかどうかわかりません。できなかった場合は、いくつかの回答(または質問)の後でこれを実行できることを願っています。私はすでにそのプロセスを理解しようとしているいくつかの情報源を見ました。 「LinuxKernelDevelopment、sec ed」という本を持っていて、それも使っています。それが説明に役立つなら、私はMIPとH8300アーキテクチャについて少し知っています。
switch_to()
を呼び出した後、カーネルスタックはnext
で指定されたタスクのスタックに切り替えられます。アドレス空間の変更などは、例えば context_switch()
。 で処理されます。schedule()
は、割り込みからも含めて、アトミックコンテキストでは呼び出すことができません(チェックイン schedule_debug()
を参照)。再スケジュールが必要な場合は、TIF_NEED_RESCHEDタスクフラグが設定されます。このフラグは、 割り込みリターンパス でチェックされます。もう少し詳しく説明すると、実際の例を次に示します。
schedule()
の実行中に割り込みます。schedule()
を直接呼び出します)、保留中のシグナルをチェックし、重要なフラグが設定されなくなるまで、 _retint_check
_ で別のラウンドに戻ります。switch_to()
について; switch_to()
(x86-32上)の機能は次のとおりです。
current_task
_の値を切り替えます。この時点で、current
は新しいタスクを指します。switch_to()
と呼ばれていた古いコードに戻る方法です。current
は新しいタスクを指しており、新しいタスクのスタックにいますが、他のさまざまなCPU状態は更新されていません。 __switch_to()
は、FPU、セグメント記述子、デバッグレジスタなどの状態の切り替えを処理します。__switch_to()
から戻ると、switch_to()
が手動でスタックにプッシュした戻りアドレスが返され、新しいのswitch_to()
の前の場所に実行が戻されます。仕事。これで、切り替えられたタスクの実行が完全に再開されました。x86-64は非常に似ていますが、ABIが異なるため、状態の保存/復元を少し増やす必要があります。