この質問の助けを借りて、知識のギャップを学び、埋めたいと思います。
したがって、ユーザーはスレッド(カーネルレベル)を実行しており、現在呼び出していますyield
(システムコールだと思います)。スケジューラは、現在のスレッドのコンテキストを TCB (カーネルのどこかに格納されている) に保存し、実行する別のスレッドを選択して、そのコンテキストをロードし、そのCS:EIP
. 物事を絞り込むために、私は x86 アーキテクチャ上で動作する Linux に取り組んでいます。それでは、詳細を説明したいと思います。
したがって、最初にシステムコールがあります。
1) のラッパー関数はyield
、システム コールの引数をスタックにプッシュします。リターン アドレスをプッシュし、システム コール番号をレジスタにプッシュして割り込みを発生させます (たとえばEAX
)。
2) 割り込みは、CPU モードをユーザーからカーネルに変更し、割り込みベクタ テーブルにジャンプし、そこからカーネル内の実際のシステム コールにジャンプします。
3) スケジューラーが呼び出され、現在の状態を TCB に保存する必要があると思います。これが私のジレンマです。スケジューラーは、その操作を実行するためにユーザースタックではなくカーネルスタックを使用するため (つまり、SS
変更SP
する必要があります)、プロセス内のレジスターを変更せずにユーザーの状態をどのように保存しますか? 状態を保存するための特別なハードウェア命令があることをフォーラムで読みましたが、スケジューラはどのようにそれらにアクセスし、誰がいつこれらの命令を実行しますか?
4) スケジューラは、状態を TCB に保存し、別の TCB をロードします。
5) スケジューラが元のスレッドを実行すると、制御がラッパー関数に戻り、スタックがクリアされ、スレッドが再開されます。
副次的な質問: スケジューラはカーネルのみのスレッド (つまり、カーネル コードのみを実行できるスレッド) として実行されますか? 各カーネル スレッドまたは各プロセスに個別のカーネル スタックはありますか?