Linux でプログラムを作成すると、何らかのバグが原因でクラッシュすることがあります。そのプログラムは中断できないプロセスとなり、コンピューターを再起動するまで (ログアウトしても) 永遠に実行され続けます。質問は次のとおりです。
- プロセスが中断不能になる原因は何ですか?
- どうすればそれを防ぐことができますか?
- おそらく愚かな質問ですが、コンピューターを再起動せずに中断する方法はありますか?
ベストアンサー1
割り込み不可能なプロセスとは、シグナルによって割り込まれることができないシステム コール (カーネル関数) 内にあるプロセスです。
それが何を意味するかを理解するには、割り込み可能なシステム コールの概念を理解する必要があります。典型的な例は ですread()
。これは、ハード ドライブの回転やヘッドの移動を伴う可能性があるため、長い時間 (数秒) かかる可能性があるシステム コールです。この時間の大半は、プロセスがスリープ状態になり、ハードウェアをブロックします。
プロセスがシステム コールでスリープしている間に、Unix 非同期シグナル (たとえば、SIGTERM) を受信すると、次のことが起こります。
- システム コールは途中で終了し、ユーザー空間に -EINTR を返すように設定されます。
- シグナルハンドラが実行されます。
- プロセスがまだ実行中の場合は、システム コールからの戻り値を取得し、同じ呼び出しを再度行うことができます。
システム コールから早期に戻ると、ユーザー空間コードはシグナルに応じてすぐに動作を変更できます。たとえば、SIGINT または SIGTERM に反応して正常に終了できます。
一方、一部のシステム コールは、このように中断することが許可されていません。システム コールが何らかの理由で停止した場合、プロセスは永久にこの強制終了できない状態のままになる可能性があります。
LWNは素晴らしい記事7月にこの話題に触れました。
元の質問に答えると:
これを防ぐには、どのドライバーが問題を引き起こしているかを特定し、使用をやめるか、カーネル ハッカーになって修正します。
再起動せずに中断不可能なプロセスを強制終了する方法: 何らかの方法でシステム コールを終了させます。多くの場合、電源スイッチを押さずにこれを行う最も効果的な方法は、電源コードを抜くことです。また、カーネル ハッカーになって、LWN の記事で説明されているように、ドライバーが TASK_KILLABLE を使用するようにすることもできます。