プロセスの概念 [Linux]

プロセスの基本

プロセスを学ぶ前に、まずコンピューターのハードウェアとソフトウェアに関する一定の基礎を身につけておく必要があります。

ハードウェアベース:フォン ノイマン アーキテクチャ

図に示すように、ハードウェアの観点から見たコンピュータのアーキテクチャです。​ 

ここでは、一般的な入力デバイスと出力デバイスをいくつか示します (一部のデバイスは出力デバイスまたは入力デバイスのみであり、一部のデバイスは出力デバイスと入力デバイスの両方として使用できます)。

入力デバイス: マイク、カメラ、キーボード、ネットワーク カード、ディスク、マウスなど。

出力デバイス: サウンド カード、グラフィック カード、ネットワーク カード、ディスク、モニター、プリンターなど。

これらのデバイスを接続する目的は、デバイス間のデータ フローです。要はデバイス間で頻繁にデータをコピーすることです。したがって、データ コピーの全体的な速度は、コンピュータの効率を決定する重要な指標となります。

従来のシナリオ: プログラムの実行中に、最初にプログラムをメモリにロードする必要があります。

プログラム ファイルには命令とデータが詰め込まれています。これらの命令とデータは最終的に CPU によって実行されます。プログラム ファイルが生成された後、ディスクに保存されます。ディスク内のファイルは、ロードする前にまずメモリにロードする必要があります。 CPUと対話します。したがって、プログラムの実行時には、まずプログラムをメモリにロードする必要があります。

ソフトウェア基盤:オペレーティング システム

オペレーティング システムは、ソフトウェアとハ​​ードウェアリソース

経営陣:データに基づいた意思決定(オペレーティングシステム)

マネージド: マネージャーの決定を実装します (ソフトウェアとハ​​ードウェア)

データ管理のコンピュータ モデリング: まず、ヒープ データ管理シナリオを特定のデータ構造の追加、削除、チェック、変更に変換し、次に特定の問題をコンピュータ レベルのモデリングに変換します。最初に説明し、次に整理する

では、プロセスとは正確には何でしょうか?

プログラムを例に挙げてみましょう。実行可能プログラムの本質は、ディスク上に保存されるバイナリ ファイルです。実行時には、まずプログラムをメモリにロードする必要があります。WeChat や QQ などのコンピュータ上のソフトウェアは、これも本質的には .exe です 実行可能プログラムは、起動時に最初にメモリにロードされる必要があります。

これらの実行可能プログラムは、メモリにロードされた後、プロセスになります。

メモリにロードした後、これらのプロセスをどのように管理すればよいでしょうか?

プロセスごとにカーネル PCB と実行可能プログラムで構成され、このカーネル PCB はプロセス制御ブロック (プロセス制御ブロック) とも呼ばれます。

このカーネル PCB は、プロセスのステータス、優先度、識別子、メモリ ポインタなどを含む構造として見ることができます。プロセス情報の属性フィールド。 プロセスの管理は、各プロセスの PCB の管理とみなすことができます。プロセスのすべての制御と操作は、プロセスの PCB にのみ関連しており、プロセスの実行可能プログラムとは何の関係もありません。プロセス!

概要: プロセス管理は、複数の PCB オブジェクトによって形成されたリンク リスト内のノードの追加、削除、確認、および変更として大まかに見ることができます。

ほとんどすべての命令はプログラムであり、メモリにロードされて実行されるとプロセスになります。 CPU の主な仕事は、メモリからの命令のフェッチ -> 命令の分析 -> 命令の実行 のサイクル内でループすることです。

CPU にはメモリ PC もあります 。PC の命令ポインタ IP/EIP には、実行される次の命令のアドレスと、命令ポインタが指すプロセスが格納されます。コードは、どのプロセスがスケジュールされるかを示します。判定命令、ループ命令、関数ジャンプ命令の本質は、メモリPC上で指す命令ポインタを変更することです。

プロセスステータス

プロセスを作成すると、システム内にプロセスが 1 つ増えます。 Linux では、通常のプロセスには親プロセスがあり、各プロセスには pid と呼ばれる番号が付けられていますが、このプロセスは新しいプロセスであるため、プロセスの pid は起動するたびにほぼ変わります。

次の世代では、親プロセスが子プロセスを作成するプロセスを通じて、新しく作成されたプロセスをテストします。

fork() 関数、ヘッダー ファイル #include

fork() 関数は子プロセスの作成に使用され、2 つの戻り値があります。 は子プロセスに 0 を返し、子プロセスの ID を親プロセスに返します。 。 (Linux では、同じ変数名を使用して異なるメモリを表すことができます) 

 #include<stdio.h>                                                                                                           
 #include<unistd.h>
 #include<stdlib.h>
 #include<sys/types.h>
 #include<sys/wait.h>
 int main()
 {
   pid_t id = fork();
   if(id == 0){
       printf("我是子进程,my_pid:%d,my_ppid:%d,return id:%d\n",getpid(),getppid(),id);
       exit(0);
   }
   else{
       printf("我是父进程,my_pid:%d,my_ppid:%d,return id:%d\n",getpid(),getppid(),id);
   }
 }  

子プロセスが作成されると、実際には親プロセスをテンプレートとして使用します。子プロセスは親プロセスのフィールド情報を浅くコピーし、コピーオンライト (書き込み時にはオープンスペースの深いコピー、それ以外の場合は浅いコピー) を使用します。作成プロセスの効率を最適化します。​ 

操作結果: 

1 つのプロセスがクラッシュすると、他のプロセスの動作に影響しますか?​ 

運用上の観点からは、これは不可能であり、どのプロセスも独立しており、相互に影響を与えることはありません。

テスト: 親プロセスがクラッシュした場合、子プロセスの動作に影響しますか?

  #include<stdio.h>                                                                                                                   
  #include<unistd.h>
  #include<stdlib.h>
  #include<sys/types.h>
  #include<sys/wait.h>
  int main()
  {
    pid_t id = fork();
    while(1)
    {
      if(id==0)
      {
  
        printf("我是子进程,my_pid:%d,my_ppid:%d,return id:%d\n",getpid(),getppid(),id);
        sleep(1);
      }
      else
      {
         printf("我是父进程,my_pid:%d,my_ppid:%d,return id:%d\n",getpid(),getppid(),id);
         sleep(1);
      }
    }
    return 0;
  }

kill -9 コマンドを使用して親プロセスを強制終了します。 

親プロセスを強制終了した後も、子プロセスはまだ実行中ですが、その ppid が変更され、「孤立プロセス」になっていることがわかります。

プロセスキューイング

プロセスが CPU 上に配置されていても、プロセスが常に実行されているわけではありません。

CPU にはタイム スライスの概念があり、CPU は実行する現在のプロセスに時間のスライス (非常に短い) を割り当て、後続のプロセスは開始時刻の順にキューに入れられます。タイム スライスが使い果たされると、現在のプロセスはまだ実行されていません。タイム スライスが終了すると、CPU はプロセスを切り替え、未完了のプロセスは引き続きキューに入れられ、次のスケジューリングを待ちます。この方法は公平かつ効率的で、プロセスのブロックやハングによる CPU リソースの浪費を効果的に防ぐことができます。

マクロの観点から見ると、あたかも多数のプログラムが同時に実行されているかのように、複数のソフトウェアを同時に開くことができます。しかし、実際には、CPU は一度に 1 つのプロセスの内容しか処理できませんが、その回転時間は非常に短く、私たちはそれに気づきませんでした。

プロセスのブロック

プロセス ブロックの概念については上で説明しましたが、プロセス ブロックの一般的なシナリオはどのようなものでしょうか?

たとえば、C言語のプログラムを実行する場合、プログラムは起動した瞬間にメモリにロードされ、プロセスを形成します。このプログラムには、ユーザーがキーボードを使用して入力する必要がある部分がありますが、ユーザーはまだ入力していません。待機プロセス中、プロセスは実行されているように見えますが、CPU は常にユーザーの入力を待機しているわけではありません。この時点で、プロセスは自身をブロッキング状態に設定し、さまざまなブロッキング タイプに応じてさまざまな待機キューに入れ、ソフトウェアまたはハードウェア リソースの準備ができるまで待機してから実行を継続します。

要約すると、プロセスがソフトウェアとハ​​ードウェアのリソースを待機していて、リソースの準備ができていない場合、プロセスは自身をブロッキング状態に設定します。ブロッキング状態のプロセスは、異なるキューに応じて複数の待機キューに接続されます。リソースを待っています!

プロセスがハングする

コンピュータのリソースが不足している場合、オペレーティング システムは優先度の低いプロセスの一部を一時停止状態に設定して外部メモリに移動し、条件が許せばプロセスはメモリに戻されます。

ゾンビプロセス

各プロセスはユーザーが必要とする特定のタスクを完了するために作成されるため、これらのプロセスには結果とデータ (プロセス ステータス) が必要です。プロセスが終了した後も、上位層が読み取るためにプロセス ステータスを独自に維持する必要があります。

プロセスが停止(終了)し、そのプロセス ステータスが親プロセスによって読み取られない場合、プロセスの現在のステータスはゾンビ状態になります。ゾンビ状態のプロセスが常に存在し、メモリが解放されず、メモリ リークが発生します。

孤立したプロセス

プロセスの親プロセスが子プロセスより先に終了(終了)した場合、子プロセスはプロセス No. 1 に採用され、孤立プロセスになります。

おすすめ

転載: blog.csdn.net/zyb___/article/details/134958123