2010-11-28 11 views
28

は、この単純なコードを考えてみましょう:フォーク後、グローバル変数は共有されていますか?

子供はMYVARをインクリメントすると、値が(pthreadのような)父と共有されている
int myvar = 0; 
int main() { 
    if (fork()>0) { 
     myvar++; 
    } else { 
     // father do nothing 
    } 
} 

+0

私はTomに同意します。あなたは両方のプロセスから値を出力して、出力が何であるかを自分で確認できました。 myvarの増加を期待していないもので眠ることを忘れないようにしてください。そうすれば、他のプロセスがインクリメントする前に実行されません。しかし、ええ、それを実行し、参照してください。 – Loduwijk

+0

誤解を招くようなコメントに注意してください。実際には、親プロセスはカウンタをインクリメントします(フォークが失敗した場合を除きます)。 –

+1

まず、障害をチェックしていません。第二に、ファイル記述子だけが共有されます。 – tchrist

答えて

39

いいえはい。

いいえ、プログラマーには見えない方法では共有されません。プロセスは独自の変数のコピーを独自に変更でき、fork()、親子、兄弟、子孫である他のプロセスに顕著な影響を与えることなく変更されます。

しかし、OSは実際にページを最初に共有します。なぜなら、forkはcopy-on-writeを実装しています。つまり、プロセスのどれもがページを変更しない限り、それらは共有されます。しかし、これは無視できる最適化です。

共有変数を使用する場合は、匿名の共有マッピング(mmap()を参照)に入れてください。実際に共有される場合は、そのすべての警告が付いています。

+0

この部分については、 'グローバル変数は親プロセスと子プロセスの間で共有できますか? ' –

3

いいえ。グローバル変数は、IPCメカニズムが実装されていない限り、プロセス間で共有されないためです。メモリ空間がコピーされます。結果として、両方のプロセスのグローバル変数は、forkの直後に同じ値を持ちますが、一方が変更されても、もう一方は変更されません。

スレッドはグローバル変数を共有します。

+0

変数がグローバルかどうかは関係ありません。 – tchrist

+0

@tchrist私が知っているように、それはオペアンプが心配しているように見えるので、グローバル化について言及します。 – Tom

32

fork()は、フォーク時に親プロセスの正確なコピーを作成します。。しかし、fork()が完了した後、その子は全く異なる存在を持ち、親に報告しません。

つまり、いいえ、親のグローバル変数は、子の変更によって変更されません。

+0

+1私は、ファイルハンドルなどのいくつかのオブジェクトが異なる環境下で共有される可能性があるため、「完全に異なる存在」は誤解を招く可能性があると主張しますが、IIRC。 –

+0

実際、「正確なコピー」の結果として、各プロセスは共有リソース(ファイル、パイプなど)に対する独自のハンドルを持ちます。実際には、同じファイルを開く2つの別々のプロセスからの違いはあまりありません。 –

+4

同じファイルを開く2つのプロセスと、フォーク前に作成されたファイル記述子を共有する2つのプロセスの間には、1つの重要な違いがあります。あるプロセスがファイルポインタを(読み書きやシークによって)動かすと、それは他のプロセスにも影響します。独立したオープンファイルの記述があるため、別々のオープンでは発生しません。参照:open()、fork()、lseek()など –

8

fork()の後、すべてのグローバル変数を含むプロセス全体が複製されます。子は、異なるPID(プロセスID)、異なる親、およびfork()が0を返したことを除いて、親の正確なレプリカです。グローバル変数は、それ自身のプロセス内ではまだグローバルです。だから答えはいいえ、グローバル変数はfork()の呼び出しの後でプロセス間で共有されません。

関連する問題