私が理解しているように、カーネルはプロセスではなく、他のプロセスの実行時に呼び出すことができる一連のハンドラーです(またはタイマーまたは同様のものを介してカーネル自体によって)。
プログラムが再実行される前に長期実行同期が必要な一部の例外ハンドラが発生した場合(ディスクの読み取りが必要なページエラーが発生した場合)、カーネルはコンテキストを切り替える必要があることをどのように認識しますか?これを達成するには、他のプロセスを実行する必要があると思いますか?
カーネルはこの状態のプロセスを断続的にチェックしてそれを処理するプロセスを作成しますか?長期実行同期ハンドラを呼び出すプロセスは、ハンドラが完了するまで(ディスクの読み取りが完了するまで)コンテキストを切り替える必要があることをカーネルに通知しますか?
答え1
「カーネルはプロセスではありません。」
これは純粋な用語です。 (用語は重要です。)プロセスは定義に従ってユーザースペースに存在するため、カーネルはプロセスではありません。しかしカーネルでは糸。
「プログラムが再実行される前に長期実行同期が必要な一部の例外ハンドラが発生した場合(ディスクの読み取りが必要なページエラーが発生した場合など)」。
ユーザー空間プロセスがマップされていないメモリページを参照するマシン命令を実行する場合:
プロセッサはトラップを生成し、次に切り替えます。リング0/管理者モード。 (これはハードウェアで発生します。)
トラップハンドラはカーネルの一部です。メモリページをディスクから取り出す必要があると仮定すると、プロセスを中断できない省電力状態に切り替えます。つまり、プロセステーブルにプロセスCPUステータスを保存し、プロセステーブルのプロセスエントリのステータスフィールドを変更します。被害者メモリページが見つかり、要求されたページ内の被害者とページをページアウトするためにI / Oが開始され、スケジューラ(カーネルの別の部分)が呼び出され、ユーザー領域コンテキストを実行する準備が整った別のプロセスに切り替えます。 。
最終的にI / Oが完了します。これにより割り込みが発生します。割り込みに応答して、プロセッサはハンドラを呼び出し、リング0/スーパーバイザモードに切り替えます。 (これはハードウェアで発生します。)
割り込みハンドラはカーネルの一部です。メモリページを待っているプロセスのI / O待機状態を消去して実行する準備が整ったことを示します。次に、スケジューラを呼び出して、ユーザーモードコンテキストを実行する準備ができたプロセスに切り替えます。
通常、カーネルは次のように実行されます。
ハードウェアトラップまたは割り込みに応答します。これにはタイマ割り込みが含まれます。
ユーザープロセスの明示的なシステムコールに応答します。
ほとんどの場合、プロセッサはリング3 /ユーザーモードにあり、一部のユーザーモードプロセスのコマンドを実行します。ユーザー空間プロセスがシステムコールを行うとき(たとえば、入出力操作を実行しようとしているため)、またはハードウェアがトラップ(誤ったメモリアクセス、ゼロで割るなど)を生成したり、割り込み要求を受信したときにハードウェア(I / O完了、タイマー割り込み、マウス移動、ネットワークインタフェースへのパケット到着など)
タイトルの質問に答えると、「カーネルスケジューラがプロセスを先取りする方法を知る方法」:カーネルはタイマ割り込みを処理します。タイマー割り込みが到着すると、スケジューラは現在実行中のユーザーモードプロセスがリソースを使い果たしたことを知ります。量子その後、プロセスは実行キューの最後に配置され、他のプロセスが再開されます。 (通常、スケジューラは、実行する準備が整ったすべてのユーザーモードプロセスが公正なプロセッサ時間共有を受けるように注意します。)
答え2
プログラムが再実行される前に長期実行同期が必要な一部の例外ハンドラが発生した場合(ディスクの読み取りが必要なページエラーが発生した場合)、カーネルはコンテキストを切り替える必要があることをどのように認識しますか?これを達成するには、他のプロセスを実行する必要があると思いますか?
ページエラーが原因でディスクの読み取りが必要な場合、カーネルページエラーハンドラはカーネルスケジューラを呼び出します。
https://elixir.bootlin.com/linux/v4.17/source/mm/filemap.c#L2470
filemap_fault()
wait_on_page_locked() - usually via __lock_page_or_retry()
wait_on_page_bit()
wait_on_page_bit_common()
io_schedule()
schedule()
私はこの質問が何を意味するのかよく理解していませんが、2番目の質問に対する答えは「いいえ、それは必要ありません」と思います。
最適化を無視すると、カーネルは常に読み取りキューに入れた直後にコンテキストを切り替えます。 (つまり、filemap_fault()
呼び出し前に発生します__lock_page_or_retry()
。ロジックは少し複雑ですが、問題なく実行できます。)
実行する他のプロセスがない場合、カーネルはCPUをアイドル操作に切り替えます。 (LinuxカーネルはCPUあたりアイドルスレッド。ただし、たとえば、Windowsの「システムアイドルプロセス」とは異なり、これは表示されませんtop
。