これが私の理解です:
- ユーザーモードでトラップ/システムコールが発生すると、レジスタはカーネルスタックに保存され、カーネルモードに切り替わり、トラップを処理してユーザーモードに戻ります。
- ユーザーモードでタイマー割り込みがオフになると、レジスタを再度保存してカーネルモードに切り替え、スケジューラに従って別のプロセスをスケジュールし、ユーザーモードに戻って2番目のプロセスを実行します。
しかし、プロセス1がすでにカーネルモードになっていて、タイマ割り込みがオフになった場合はどうなりますか?それではどうなりますか?
答え1
一般的に言うと(Linuxカーネルがこれをどのように実装するのかわかりません)、割り込みがトリガされると、実行中のコードが停止し、すべてのレジスタが保存され、CPUは割り込みを処理する割り込みサービスルーチンを実行します。その後、レジスタが復元され、コードの実行が継続されます。
このような状況を防ぐ唯一の方法は、割り込みをディセーブルすることです。割り込みは通常、アトミック操作を処理するためにマイクロコントローラで実行されます。通常、割り込みサービスルーチンが実行する最初の作業は、割り込みを無効にすることです(それ自体は中断できません)。タスクが完了した後に最後に実行されるタスクは、割り込みを再び有効にすることです。
繰り返しますが、私はLinuxカーネルでの割り込みサービスルーチンの正確な実装に慣れていませんが、同じように動作することを期待しています。
x86アーキテクチャからユーザーモードからカーネルモードへのモード切り替えはここでは起こらないようです。これは、ISRがカーネルモードで実行され、CPUがカーネルモードに移行する必要があると仮定すると回避できます。すでにカーネルモードになっている場合は、レジスタを保存してISRにジャンプしてください。その後、中断前に実行していたコードが何であれ、コードが実行されていたモードで再起動します。