このセクションの主な内容:
1.プロセスの作成
2.プロセスの終了
3.プロセスの待機
プロセスの作成
1. fork()関数:
#include <unistd.h>
pid_t fork(void);
//返回值:子进程中返回0,父进程返回子进程id,出错返回-1
- fork()関数の役割はプロセスを作成することであり、fork()関数はシステムコールです。
- 親プロセスがfork()関数を呼び出して子プロセスを作成した後、子プロセスは親プロセスPCBをコピーし、親プロセスと子プロセスは2つの独立したプロセスです。
- 子プロセスは、fork()関数の後のコードから実行を開始し、プログラムカウンター(プログラムによって実行される次の命令を保存する)およびコンテキストデータ(レジスターに値を保存する)をどのように実行するかを認識します。
詳細な紹介については、前の記事「fork()関数について話す」を参照してください。
2.vfork()関数
- vfork()関数は子プロセスを作成することもできます。fork()との違いは、vfork()関数によって作成された子プロセスが親プロセスPCBをコピーし、子プロセスのメモリポインタが同じ仮想アドレスを指すことです。親プロセスとしてのスペース、つまり親プロセスと子プロセスは仮想アドレススペースを共有します。
- 問題:コールスタックが台無しになっている
- vfork()関数は、子プロセスを最初に実行し、次に子プロセスの実行後に親プロセスを実行することで、この問題を解決します。
- 現時点ではほとんど使用されていません
オンラインでコピーされた段落を理解できます:
vforkがある理由、前のforkは非常にばかげているため、子プロセスを作成すると、新しいアドレス
スペースが作成され、親プロセスのリソースがコピーされますが、多くの場合、子プロセスにありますprocess exec呼び出しが実行されるため、のコピー作業の最前線は
無駄になります。この場合、賢い人はvforkを思い付き、開始したばかりの子が一時的に生成
し、親プロセスのアドレス空間を共有します(実際にはスレッドの概念)、今回は実行中の親プロセスのアドレス空間で子プロセスが
実行されているため、子は書き込むことができず、息子を占有します。「家の父、私は
ケースに不満を払い、彼を脱出させます(ブロッキング)の後、息子がexecまたはexitを実行すると、彼は自分の
家を購入し、この時点で彼は分離されます。元のリンク:https://blog.csdn.net/jianchi88/article/details/6985326
プロセスの終了
1.コンセプト
つまり、プロセスは終了し、次の2つのシナリオに分けられます。
1.コードの実行後、main関数から戻ると、操作の結果が正しい場合と正しくない場合があります。
2.コードの実行が終了せず、直接クラッシュしました(メモリアクセスが範囲外、逆参照されたnullポインター、ダブルフリー、ctrl + c、killコマンド)
2.プログラムの終了方法
1.メイン関数の戻り値2.exit()関数を呼び出し
ます:ライブラリ関数、Cライブラリでプログラマーに提供される関数
3. _exit()関数を呼び出します:システム呼び出し、プログラマーによって提供される関数オペレーティング・システム
void exit(int status);
//status:进程在在退出的时候,可以指定退出码是多少
//echo $? //能够获取最后一个终止进程的退出码
exit()関数と_exit()関数の違いを図に示します。
1. exit()関数は、ユーザー定義のクリーンアップ関数を実行します
カスタムクリーンアップ関数:
int atexit(void\*(\*fuction)(void));
パラメーターは関数ポインター:戻り値はvoid、パラメーターはvoid
関数:atexit()関数を呼び出し、パラメーターは関数のアドレスであり、この関数のアドレスは保存されます。そして、プロセス終了関数のときにこれを呼び出します。2. exit()関数はバッファを更新します
_exit()がフラッシュしないのに、exit()関数がバッファをフラッシュするのはなぜですか?
- 1.バッファは、カーネルではなくCライブラリで維持されます
- 2. _exit()関数を直接呼び出してカーネルコードを直接実行すると、バッファーは更新されません。
- 3. exit()関数が呼び出されると、プロセスが終了する前に、バッファー内のデータが最初に更新され、次にプロセスが終了します。
バッファを更新する方法は?
- main()関数から戻る
- \ nバッファは更新できます
- フラッシュ機能により、バッファを強制的にフラッシュできます
- exit()関数もバッファを更新します
プロセス待機
1.役割:ゾンビプロセスの生成を防ぐため
2.インターフェース:pid_t wait(int* status)
statusは、オペレーティングシステムによって割り当てられる出力パラメータです。
ここで、ステータスはint型で、4バイトを占有し、最後の2バイトのみを使用します。実際の有効値は、最後の2バイトです。
プロセスが正常に終了した場合:
プロセスが異常終了した場合:
3.使用方法
子プロセスを作成し、子プロセスは通常のロジックを実行し、親プロセスはwait()関数を呼び出してブロックして待機します。子プロセスが終了すると、親プロセスは待機しているため、子プロセスはゾンビプロセスにはなりません。
- ブロッキング:呼び出し元の関数が特定の条件が成熟するのを待つ必要がある場合、関数は戻ります。条件が成熟していない場合は、永久に待機します。
- ノンブロッキング:呼び出し元の関数が特定の条件が成熟するのを待つ必要がある場合、関数は戻ります。条件が成熟していない場合は、エラーで戻ります。
ゾンビプロセスの生成を整理するには:
子プロセスが終了し、親プロセスが子プロセスの終了シグナルSIGCHLDを受信しますが、親プロセスはSIGCHLDシグナルを無視するため、子プロセスのリソースを解放できません。
プロセスが待機している間、親プロセスが受信したSIGCHLDシグナルが処理され、子プロセスはゾンビプロセスを発生させることなく正常に終了します。
さらに、プロセス待機関数waitpid()があります。
パラメトリックモデル:
pid_t waitpid(pid_t pid, int* status, int options);
パラメータの意味:
pid:waitpid関数に
、どの子プロセスを待機するかを指示します。pid= -1は、子プロセスを待機することを意味します。
pid> 0は、指定された子プロセスを待機していることを意味します。子プロセスのプロセス番号は、着信pidの値です。
status:待機中のstatusパラメータの意味と一致します
オプション:waitpid関数がブロックするか非ブロックにするかを設定します
0:ノンブロッキング
WNOHANG:ノンブロッキング、つまり、子プロセスが終了しない場合、waitpid関数はエラーを返します
waitpid(pid> 0、status、0)===>はwait()関数と同等です
wait()関数はwaitpid関数を呼び出すことで実装されます