カーネルがシステムコールの処理中にスリープ状態になる可能性がある場合、実行はどのようにシステムコールに戻りますか?

カーネルがシステムコールの処理中にスリープ状態になる可能性がある場合、実行はどのようにシステムコールに戻りますか?

私はRobert Loveの「Linux Kernel Development」を読んでいました。現在のポインタは、システムコールを発行したプロセスである現在のジョブを指します。

私が理解していないのは、システムコールがスリープ状態のときに実行がシステムコールに戻る方法です。プロセスコンテキストで実行している場合は、ウェイクアップして再スケジュールできますが、ユーザープロセスはカーネルスペースで実行できません。システムコールが呼び出されると、カーネルはそのシステムコールを実行するためのジョブ/プロセスを生成しますか?ユーザー空間のシステムコールによってトラップがカーネルモードに切り替わり、そのシステムコールが実行されることがわかりましたが、この記事を読む前にシステムコールがスリープしてスケジュールを変更できないと仮定しましたが、それを行う必要がある理由を理解しています。 。

答え1

重要な部分はこんな感じです。

ユーザープロセスはカーネル空間で実行できません

これは正確ではありません。 Robert Loveは、システムコールがプロセスコンテキストで実行されると書いていることは、基本的にプロセスがシステムコールを実行するためにカーネルモードで実行されていることを意味します。カーネルがシステムコールを処理しているときにまだ呼び出しプロセスであるプロセスで実行されています。スケジュールを変更することを決定すると、プロセスは一時停止され、スケジュールされた他のプロセスの中で実行が続行されます。

中断されたプロセスが再開されると、カーネルモードでシステムコールを実行し続けます。

2.6スケジューリングの大きな変化の1つは、以前はユーザーモードでのみプロセスを中断できることです。これで、ユーザーモードでのみプロセスを停止できます。プリエンプティブカーネルを使用すると、カーネルモードでプロセスが中断される可能性があります(カーネルコードの重要な部分で実行されるプリエンプションを無効にしない限り)。

答え2

ユーザープロセスはカーネル空間で実行できないため、読者を混同しないでください。ジョブが何であれ、read()、ioctl()、または他のものであれ、libcを介して "syscall"アセンブリコマンド(x86_64)で終わります。これにより、カーネル空間に対するブリッジである sw 割り込みが発生し、ハンドラが完了すると制御権をユーザ空間に返します。

関連情報