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フラグ
  • 環境
  • 接続された共有メモリセグメント
  • メモリマッピング
  • リソースの制限