アドレス空間からのフォークを理解する
http:// wsfdl.com/linux/2015/04/06/アドレス空間からfork.htmlを理解する
Linuxプロセスアドレス空間
high address +---------------+
| |
| Stack | int local_b
| |
+---------------+
| | |
| v |
| |
| |
| ^ |
| | |
+---------------+
| |
| Heap | int * heap_c = malloc()
| |
+---------------+
| Data | int global_a
+---------------+
| Code |
low address +---------------+
上の画像はLinuxのプロセスアドレス空間です。低から高までのアドレスは次のとおりです。
- コードセグメント:プログラムのコード、CPUによって実行される命令の一部、読み取り専用で共有
- データセグメント:初期化されたデータセグメントと初期化されていないデータセグメントに分割でき、グローバル変数などを格納するためによく使用されます。
- スタック:関数と自動変数(静的変数が追加されていない自動変数はローカル変数とも呼ばれます)
- ヒープ:malloc()によって割り当てられたメモリなどのメモリを動的に割り当てる
詳細な概要については、メモリ内のプログラムの構造を参照してください 。
フォーク
Parent Process Child Process
high address +---------------+ +---------------+
| | | |
| Stack | | Stack |
| | | |
+---------------+ +---------------+
| | | | | |
| v | | v |
| | | |
| | | |
| ^ | | ^ |
| | | | | |
+---------------+ +---------------+
| | | |
| Heap | | Heap |
| | | |
+---------------+ +---------------+
| Data | | Data |
+---------------+----------+---------------+
| Code |
low address +------------------------------------------+
Fork はLinuxで最も重要なシステムコールの1つです。新しいプロセスを作成するために使用されます。これは、親プロセスのアドレススペースのデータセグメント、ヒープ、スタックを完全にコピーしますが、親プロセスとコードセグメントを共有します。論理的な観点から、子プロセスと親プロセスのメモリアドレススペースは互いに独立しており、子プロセスは自身のデータセグメントを変更し、ヒープとスタックは親プロセスのメモリスペースに影響を与えません。forkを呼び出すたびに2つの結果が返されます。親プロセスの戻り値は子プロセスのpidであり、子プロセスの戻り値は0です。
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
int global_a = 0; // data segment int main(void) { int local_b = 0, status; // stack int * heap_c = malloc(sizeof(int)); // heap pid_t pid; if(!fork()){ global_a ++; local_b ++; *heap_c = 1; exit(0); } else{ wait(&status); } printf("global_a = %d, local_b = %d, heap_c = %d\n", global_a, local_b, *heap_c); }
プログラムの出力は次のとおりです。
$ ./a.out
global_a = 0, local_b = 0, heap_c = 0
注:fork呼び出しのオーバーヘッドを削減するために、実際にはコピーオンライト(COW) テクノロジーが使用され ます。
親プロセスと子プロセスの両方で共有されるプロパティ
親と子プロセスのアドレス空間が独立しているが、二つは、まだ他の多くのリソースを共有しますが、からの抜粋 UNIX環境、第3版では、プログラミング上級:
- ファイル記述子
- 実ユーザーID、実グループID、実効ユーザーID、実効グループID
- 補足グループID
- プロセスグループID
- セッションID
- 制御端末
- set-user-IDフラグとset-group-IDフラグ
- 現在の作業ディレクトリ
- ルートディレクトリ
- ファイルモード作成マスク
- 信号マスクと処理
- 開いているファイル記述子のclose-on-execフラグ
- 環境
- 接続された共有メモリセグメント
- メモリマッピング
- リソースの制限