ホームページ >運用・保守 >Linuxの運用と保守 >Linuxプロセスにはいくつかの状態があります

Linuxプロセスにはいくつかの状態があります

青灯夜游
青灯夜游オリジナル
2023-03-13 10:11:248487ブラウズ

Linux プロセスには 6 つの状態があります: 1. R 実行可能状態、この状態のプロセスのみが CPU 上で実行できます; 2. S 割り込み可能なスリープ状態、この状態のプロセスは何かを待っています イベントが発生し、中断されます; 3. D 中断不可能なスリープ状態、プロセスはスリープ状態ですが、現時点ではプロセスは中断不可能です; 4. T 一時停止状態または追跡状態、プロセスに SIGSTOP 信号を送信すると、プロセスは応答して T 状態に入ります。 5. Z ゾンビ状態、プロセスが停止しつつあることを示します 6. X 死状態。

Linuxプロセスにはいくつかの状態があります

#このチュートリアルの動作環境: linux7.3 システム、Dell G3 コンピューター。

Linux では、プロセスには 6 つの状態があります。つまり、実行可能状態、割り込み可能なスリープ状態、割り込み不可のスリープ状態、一時停止状態または追跡状態、ゾンビ状態、および死亡状態です。

Linuxプロセスステータス詳細説明

R(TASK_RUNNING)実行可能ステータス

これだけこの状態のプロセスのみが CPU 上で実行できます。同時に複数のプロセスが実行可能状態にある可能性があり、これらのプロセスの task_struct 構造体 (プロセス制御ブロック) は、対応する CPU の実行可能キューに配置されます (プロセスは 1 つの CPU の実行可能キューに同時に存在できます)ほとんど)。プロセス スケジューラのタスクは、各 CPU の実行可能キューからプロセスを選択し、その CPU 上で実行することです。

多くのオペレーティング システムの教科書では、CPU 上で実行中のプロセスを RUNNING 状態、実行可能だが実行がスケジュールされていないプロセスを READY 状態として定義しています。これら 2 つの状態は TASK_RUNNING 状態に統合されます。 Linux 上で。

S(TASK_INTERRUPTIBLE) 割り込み可能なスリープ状態

この状態のプロセスは、特定のイベントが発生するのを待っています (ソケット接続の待機、タスクの待機など)。セマフォ)、停止されました。これらのプロセスの task_struct 構造体は、対応するイベントの待機キューに入れられます。これらのイベントが発生すると (外部割り込みによってトリガーされるか、他のプロセスによってトリガーされて)、対応する待機キュー内の 1 つ以上のプロセスが起動されます。

ps コマンドを実行すると、通常の状況では、プロセス リスト内のプロセスの大部分が TASK_INTERRUPTIBLE 状態にあることがわかります (マシンの負荷が非常に高い場合を除く)。結局のところ、CPU は 1 つか 2 つしかなく、多くの場合、数十、数百のプロセスが存在します。プロセスのほとんどがスリープ状態でない場合、CPU はどのように応答できるでしょうか?

D(TASK_UNINTERRUPTIBLE) 中断不可能なスリープ状態

TASK_INTERRUPTIBLE 状態と同様に、プロセスはスリープ状態ですが、現時点ではプロセスは中断不可能です。割り込み不可能とは、CPU が外部ハードウェアからの割り込みに応答しないことを意味するのではなく、プロセスが非同期信号に応答しないことを意味します。

ほとんどの場合、プロセスはスリープ状態にあるときに常に非同期信号に応答できるはずです。そうしないと、kill -9 がスリープ状態のプロセスを強制終了できないことに驚くでしょう。したがって、ps コマンドで表示されるプロセスが TASK_UNINTERRUPTIBLE 状態になることはほとんどなく、常に TASK_INTERRUPTIBLE 状態になる理由も簡単に理解できます。

TASK_UNINTERRUPTIBLE 状態の重要性は、カーネルの特定の処理フローを中断できないことです。非同期信号に応答すると、プログラムの実行フローに非同期信号を処理する処理が挿入されます(この挿入された処理はカーネルモードのみに存在する場合もあれば、ユーザーモードにまで拡張される場合もあります)ので、元の処理は中断される。

プロセスが特定のハードウェア上で動作するとき (たとえば、プロセスは特定のデバイス ファイルを読み取るために read システム コールを呼び出し、最終的に read システム コールは対応するデバイス ドライバのコードを実行し、対応するデバイス ドライバと通信します)物理デバイスの相互作用)、プロセスとデバイス間の相互作用が中断されてデバイスが制御不能な状態に陥るのを防ぐために、TASK_UNINTERRUPTIBLE 状態を使用してプロセスを保護することが必要になる場合があります。この場合の TASK_UNINTERRUPTIBLE 状態は常に非常に短期間であり、基本的に ps コマンドでキャプチャすることは不可能です。

Linux システムでは簡単にキャプチャできる TASK_UNINTERRUPTIBLE 状態もあります。 vfork システム コールの実行後、子プロセスが exit または exec を呼び出すまで、親プロセスは TASK_UNINTERRUPTIBLE 状態に入ります。

T(TASK_STPPED または TASK_TRACED) サスペンド状態またはトレース状態

プロセスに SIGSTOP シグナルを送信すると、シグナルに応答して TASK_STOPPED 状態に入ります (ただし、プロセス自体が TASK_UNINTERRUPTIBLE 状態にあり、シグナルに応答しない場合は除きます)。 (SIGSTOP は、SIGKILL シグナルと同様に、非常に必須です。ユーザー プロセスは、シグナル シリーズ システム コールを通じて、対応するシグナル処理関数をリセットすることはできません。)

SIGCONT シグナルをプロセスに送信すると、プロセスが変更される可能性があります。 TASK_STOPPED 状態から TASK_RUNNING 状態に戻します。

プロセスがトレースされているとき、プロセスは TASK_TRACED という特殊な状態になります。 「追跡中」とは、プロセスが一時停止され、追跡しているプロセスがそのプロセスを操作するのを待っていることを意味します。たとえば、gdb で追跡対象のプロセスにブレークポイントを設定した場合、プロセスはブレークポイントで停止すると TASK_TRACED 状態になります。また、追跡されるプロセスが依然として前述の状態にある場合もあります。

プロセス自体の場合、TASK_STOPPED と TASK_TRACED の状態は非常に似ており、どちらもプロセスが一時停止されていることを示します。

TASK_TRACED 状態は、TASK_STOPPED の上に追加された保護層に相当します。TASK_TRACED 状態のプロセスは、SIGCONT 信号に応答して起動することはできません。デバッグされたプロセスは、デバッグ プロセスが ptrace システム コールを通じて PTRACE_CONT や PTRACE_DETACH などの操作を実行するか (操作は ptrace システム コールのパラメーターで指定されます)、またはデバッグ プロセスが終了するまでのみ、TASK_RUNNING 状態に戻ることができます。

Z(TASK_DEAD - EXIT_ZOMBIE) ゾンビ状態、プロセスはゾンビプロセスになります

プロセスは終了プロセス中に TASK_DEAD 状態になります。

この終了プロセス中に、task_struct 構造体 (およびいくつかのリソース) を除いて、プロセスによって占有されているすべてのリソースがリサイクルされます。したがって、プロセスには task_struct の空のシェルだけが残るため、ゾンビと呼ばれます。

task_struct が保持される理由は、task_struct がプロセスの終了コードといくつかの統計情報を格納するためです。そして、その親プロセスはこの情報を気にする可能性があります。例えばシェルでは、$?変数に最後に終了したフォアグラウンドプロセスの終了コードが格納されており、この終了コードがif文の判定条件としてよく使われます。

もちろん、カーネルはこの情報を別の場所に保存し、task_struct 構造体を解放してスペースを節約することもできます。ただし、pid から task_struct への検索関係がカーネル内で確立されており、プロセス間の親子関係も確立されているため、task_struct 構造体を使用する方が便利です。 task_struct を解放するには、親プロセスが子プロセスの終了情報を見つけられるように、いくつかの新しいデータ構造を作成する必要があります。

親プロセスは、一連の wait4 システム コール (wait4、waitid など) を通じて 1 つまたはいくつかの子プロセスの終了を待機し、その終了情報を取得できます。その後、一連の wait システムコールによって子プロセス (task_struct) の本体も解放されます。

子プロセスが終了すると、カーネルは親プロセスにシグナルを送信して、「死体を回収する」ように親プロセスに通知します。このシグナルのデフォルトは SIGCHLD ですが、clone システム コールを介して子プロセスを作成するときにこのシグナルを設定できます。

親プロセスが存在しない限り、このゾンビ状態の子プロセスは常に存在します。では、親プロセスが終了した場合、子プロセスの「死体を回収」するのは誰になるのでしょうか?

プロセスが終了すると、そのすべての子プロセスは他のプロセスによってホストされます (他のプロセスの子プロセスになります)。誰に託されているのか?これは、既存のプロセス (存在する場合) のプロセス グループ内の次のプロセス、またはプロセス番号 1 である可能性があります。したがって、すべてのプロセス、すべての瞬間に親プロセスがあります。プロセス番号 1 でない限り。

プロセス No. 1 (pid 1 のプロセス) は、init プロセスとも呼ばれます。 Linux システムの起動後、最初に作成されるユーザー モード プロセスは init プロセスです。

  • システム初期化スクリプトを実行し、一連のプロセスを作成します (これらはすべて init プロセスの子孫です);

  • 無限ループで子プロセスの終了イベントを待ち、waitid システム コールを呼び出して「死体収集」作業を完了します。

init プロセスは一時停止されません。 kill (これはカーネルによって保証されています)。子プロセスが終了するのを待っている間は TASK_INTERRUPTIBLE 状態になり、「回復」プロセス中は TASK_RUNNING 状態になります。

XX(TASK_DEAD - EXIT_DEAD) 死亡状態、プロセスは破壊されようとしています

また、プロセスは終了プロセス中に task_struct を保持しない可能性があります。たとえば、このプロセスは、マルチスレッド プログラムでは切り離し可能なプロセスです。

または、親プロセスは、SIGCHLD シグナルのハンドラーを SIG_IGN に設定することで、SIGCHLD シグナルを明示的に無視します。 (これは POSIX 仕様ですが、子プロセスの終了シグナルは SIGCHLD 以外のシグナルに設定できます。)

この時点で、プロセスは EXIT_DEAD 終了ステータスになります。これは、次のことを意味します。次のコードをすぐに実行すると、プロセスが完全に解放されます。したがって、EXIT_DEAD 状態は非常に短期間であり、ps コマンドでキャプチャすることはほとんど不可能です。

プロセスの初期状態

プロセスは、一連の fork システム コール (fork、clone、vfork) を通じて作成されます。カーネル (またはカーネル モジュール) は、kernel_thread 関数を通じてカーネル プロセスを作成することもできます。サブプロセスを作成するこれらの関数は、基本的に同じ機能を実行します。つまり、呼び出しプロセスをコピーしてサブプロセスを取得します。 (オプションパラメータを使用して、さまざまなリソースを共有するかプライベートにするかを決定できます。)

つまり、呼び出しプロセスは TASK_RUNNING 状態にあるため (そうでない場合、実行中でない場合、どうやって呼び出すことができるでしょうか?)、子プロセスもデフォルトで TASK_RUNNING 状態になります。さらに、システム コール clone およびカーネル関数 kernel_thread も CLONE_STOPPED オプションを受け入れるため、子プロセスの初期状態が TASK_STOPPED に設定されます。

プロセス ステータスの変更

プロセスが作成された後、プロセスが終了するまでステータスは一連の変更を受ける可能性があります。いくつかのプロセス状態がありますが、プロセス状態の変化には 2 つの方向しかありません - TASK_RUNNING 状態から非 TASK_RUNNING 状態へ、または非 TASK_RUNNING 状態から TASK_RUNNING 状態へ。

言い換えると、SIGKILL シグナルが TASK_INTERRUPTIBLE 状態のプロセスに送信されると、プロセスはまず起動され (TASK_RUNNING 状態に入り)、次に SIGKILL シグナルに応答して終了します (TASK_RUNNING 状態に変わります)。 TASK_DEAD 状態)。 TASK_INTERRUPTIBLE 状態から直接終了することはありません。

プロセスは、ウェイクアップ操作を実行する他のプロセス (割り込みハンドラーの場合もあります) によって、非 TASK_RUNNING 状態から TASK_RUNNING 状態に変化します。覚醒を実行するプロセスは、覚醒したプロセスのステータスを TASK_RUNNING に設定し、その task_struct 構造体を CPU の実行可能キューに追加します。その後、目覚めたプロセスの実行をスケジュールする機会が得られます。

プロセスが TASK_RUNNING 状態から非 TASK_RUNNING 状態に変化するには 2 つの方法があります。

  • シグナルに応答して、プロセスは TASK_STOPED 状態に入るか、またはTASK_DEAD 状態;

  • システム コールを実行して、積極的に TASK_INTERRUPTIBLE 状態 (nanosleep システム コールなど) または TASK_DEAD 状態 (exit システム コールなど) に入るか、または TASK_INTERRUPTIBLE 状態に入る、またはシステムコールの実行に必要なリソースが満たされないため、 TASK_UNINTERRUPTIBLE ステータス (システムコールの選択など)。

明らかに、これらの状況は両方とも、プロセスが CPU で実行されているときにのみ発生します。

#Linux プロセス ステータスの説明

##ステータス記号R#STASK_INTERRUPTIBLE割り込み可能なスリープ状態、信号を処理可能D TASK_UNINTERRUPTIBLE中断のないスリープ状態、信号は遅延ありで処理可能#TTASK_STOPPED または TASK_TRACED 一時停止状態または追跡状態、コードを実行するタイム スライスがないため信号を処理できませんZTASK_DEAD - EXIT_ZOMBIE終了ステータス、プロセスがゾンビプロセスになります。強制終了できません。つまり、タスク シグナルに応答せず、SIGKILL で強制終了できません。拡張知識: 待機キューとは何ですか、実行キューとは何ですか?キュー、およびハング / ブロッキングとは何ですか? プロセスのウェイクアップとは何ですか? CPU によってスケジュールされることをプロセスのウェイクアップといいます
ステータスの完全名 Description
TASK_RUNNING 実行可能ステータスと実行ステータス (run_queue キュー内のステータス)

プロセスが実行されているとき (動作条件の一部がまだ準備されていないため) (たとえば、ネットワークが必要だがネットワーク カードが利用できない、または IO を待つ必要がある、つまり周辺機器を使用する必要がある)、待機キューに配置され、task_struct のステータス ビットがS/Dにも変更可能です。 プロセスが S/D 状態にある場合、プロセスは周辺機器 (ネットワーク カード、ディスク モニターなど) を使用するために待機キューで待機します。 CPU は実行キューと呼ばれます。セットアップしたデバイスは待機キューと呼ばれます。

いわゆるプロセスは、実行中に、運用上のニーズにより異なるキューに存在する場合があります。

別のキューにある、ステータスは異なります。

プロセスが R 状態にあるとき、特定のペリフェラルが必要であるが、そのペリフェラルが使用されている場合は、状態を S/D に変更してから、task_struct Put を変更します。待機キューにあります

関連する推奨事項:「

Linux ビデオ チュートリアル

以上がLinuxプロセスにはいくつかの状態がありますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。