2011-01-04 3 views
26

私は親プロセスと子プロセスを持つプログラムを持っています。 fork()の前に、親プロセスはmalloc()を呼び出し、配列をいくつかのデータで埋めました。 fork()の後、子はそのデータを必要とします。私は、パイプを使用することができることを知っているが、次のコードが動作するように表示されます。特に、fork()はLinuxのmalloc()から動的に割り当てられたメモリをどのように扱いますか?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 

int main(int argc, char *argv[]) { 
    char *array; 
    array = malloc(20); 
    strcpy(array, "Hello"); 
    switch(fork()) { 
    case 0: 
     printf("Child array: %s\n", array); 
     strcpy(array, "Goodbye"); 
     printf("Child array: %s\n", array); 
     free(array); 
     break; 
    case -1: 
     printf("Error with fork()\n"); 
     break; 
    default: 
     printf("Parent array: %s\n", array); 
     sleep(1); 
     printf("Parent array: %s\n", array); 
     free(array); 
    } 
    return 0; 
} 

出力は次のとおりです。

Parent array: Hello 
Child array: Hello 
Child array: Goodbye 
Parent array: Hello 

私がスタックに割り当てられたデータが子供で利用可能であることを知っているが、ヒープに割り当てられたデータも子プロセスで使用できるように見えます。同様に、子はスタック上の親のデータを変更することはできません。子はそのヒープ上の親のデータを変更することはできません。だから私は子供がスタックとヒープの両方のデータの独自のコピーを取得すると仮定します。

これはLinuxでは常にそうですか?もしそうなら、これをサポートするドキュメントはどこですか?私はfork()のマニュアルページをチェックしましたが、ヒープ上に動的に割り当てられたメモリは特に記述しませんでした。

は、プロセスに割り当てられている各ページが(それはそれでスタックまたはヒープを持つ仮想メモリページである)、それにアクセスできるようにフォークプロセスのためにコピーされます。あなたに

答えて

30

ありがとうございました

実際には、最初にコピーされません。コピーオンライトに設定されています。つまり、プロセスの1つ(親または子)がコピーされたページを修正して害を及ぼさないようにするone-anotherであり、それらにアクセス可能なfork()のポイントからのすべてのデータを保持しています。

たとえば、実際の実行可能ファイルがメモリ内にマップされたコードページは、通常読み取り専用なので、フォークされたすべてのプロセスの間で再利用されます。誰もそこに書き込むことはないため、読んだり、コピーオンライトをする必要はありません。

さらに詳しい情報はとhereです。

+0

OPコードには*競合状態はありません。 – SiegeX

+3

このメモリを使用してプロセスが通信できなくなることはありません。 – abyx

+0

Nitpick: 'mmap(MAP_SHARED)'と 'shmat'を考慮してください。 Cの "スタック"と "ヒープ"の範囲外ですが、あなたは "各ページ"と言っています... – ephemient

4

フォーク後、子は親から完全に独立していますが、親のコピーである特定のものを継承することがあります。ヒープの場合、子は概念的にフォーク時に親ヒープのコピーを持ちます。しかしながら、子供のアドレス空間における頭部の修正は、子供のコピーを変更するだけである(例えば、コピーオンライト)。ドキュメントについては

:私は、そのドキュメントは通常、すべてがコピーされていることを何とか、何とか何とかのため以外を記載します気づきました。

2

短い答えは「書くのは汚い」 - 長い答えはもっと長くなります。

しかし、Cレベルで想定するのが安全である作業モデルは、fork()の直後に2つのプロセスが完全に同一である、つまり子プロセスが完全に100% fork()の戻り値の周りにちょっとしたビットがあります)。そして、それぞれの側がメモリ、スタック、ヒープを変更するにつれて発散し始めます。

あなたの結論はわずかですが、子供は自分のスペースにコピーされた親と同じデータで始まり、それを修正して、それが変更されたものと見なします。

実際には、複雑なものがあります。汚いものを実行して完全なコピーを回避しようとするためです。それができるまでコピーを避ける。

Dw。

関連する問題