web-dev-qa-db-ja.com

特に、fork()はLinuxでmalloc()から動的に割り当てられたメモリをどのように処理しますか?

親プロセスと子プロセスを持つプログラムがあります。 fork()の前に、親プロセスがmalloc()を呼び出し、配列にデータを入れました。 fork()の後、子はそのデータを必要とします。パイプを使用できることはわかっていますが、次のコードが機能するようです。

#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()のマニュアルページを確認しましたが、ヒープに動的に割り当てられたメモリについては具体的には触れられていませんでした。

ありがとうございました

34
pcd6623

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

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

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

詳細は here および here を参照してください。

37
abyx

フォークの後、子は親から完全に独立していますが、親のコピーである特定のものを継承する場合があります。ヒープの場合、子は概念的に、フォーク時に親ヒープのコピーを保持します。ただし、子のアドレススペースのヘッドを変更しても、子のコピーのみが変更されます(たとえば、コピーオンライトによって)。

ドキュメントに関して:私はドキュメントが通常すべてがコピーされると述べていることに気づきましたexcept何とか何とか何とか.

5
Noah Watkins

短い答えは「書き込みのダーティ」です。長い答えは..ずっと長くなります。

しかし、すべての意図と目的のために-Cレベルで安全に想定できる作業モデルは、fork()の直後に2つのプロセスが完全に同一であることです。つまり、子は100%正確なコピーを取得します(ただし、 fork())の戻り値の周りを少し-そして、両側がメモリ、スタック、ヒープを変更するにつれて、分岐が始まります。

したがって、あなたの結論は少しずれています-子は、親と同じデータを自分のスペースにコピーして開始し、次にそれを変更します-親が自分のコピーを続行している間、それを変更されたと見なします。

実際には少し複雑です-それは汚いことをすることによって完全なコピーを避けようとするからです。必要になるまでコピーしないようにします。

Dw。