3

私は2つの新しいプロセスをフォークするC++のこのプログラムを持っています:

#include <pthread.h>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdlib>
using namespace std;

int shared;

void func(){
  extern int shared;
  for (int i=0; i<10;i++)
        shared++;
  cout<<"Process "<<getpid()<<", shared "
        <<shared<<", &shared "
        <<&shared<<endl;
}

int main(){
  extern int shared;
  pid_t p1,p2;
  int status;
  shared=0;
  if ((p1=fork())==0) {func();exit(0);};
  if ((p2=fork())==0) {func();exit(0);};
  for(int i=0;i<10;i++)
        shared++;
  waitpid(p1,&status,0);
  waitpid(p2,&status,0);;
  cout<<"shared variable is: "<<shared<<endl;
  cout<<"Process "<<getpid()<<", shared "
        <<shared<<", &shared "
        <<&shared<<endl;
}

2つのフォークされたプロセスは共有変数をインクリメントし、親プロセスも同じことを行います。変数は各プロセスのデータセグメントに属しているため、増分は独立しているため、最終的な値は10になります。

ただし、共有変数のメモリアドレスは同じであるため、プログラムの出力をコンパイルして監視してみてください。それはどのように説明できますか?それは理解できません。fork()がどのように機能するかは知っていると思いましたが、これは非常に奇妙に思えます。

別々の変数ですが、アドレスが同じである理由について説明する必要があります。

4

5 に答える 5

12

OSは、仮想メモリおよび同様の手法を使用して、各プロセスが同じアドレスにある異なるメモリセル(仮想または読み取り)を確実に認識できるようにします。明示的に共有されているメモリ(たとえば、shmを介して)のみが共有されます。デフォルトでは、すべてのメモリは個別のプロセス間で分離されています。

于 2009-08-10T00:51:08.153 に答える
8

これは「仮想アドレス」と呼ばれます。各プロセスには独自のアドレス空間があり、各アドレスはプロセスに応じて異なる意味を持ちます。fork()は、データを共有する代わりにコピーを作成します(技術的には、コピーオンライトで共有される場合がありますが、これは先行コピーと同じ効果があります)。IOW、変数「shared」はプロセス間で共有されません。

于 2009-08-10T00:51:23.177 に答える
4

最新のシステムのポインタは、実際のハードウェアメモリアドレスに対応していません。むしろ、アドレスはオペレーティングシステムによって管理される仮想空間にマップされます。したがって、2つの異なるプロセスのポインタアドレスは、実際には同じではないのに同じように見える可能性があります。

于 2009-08-10T00:51:10.120 に答える
0

これは pthread_mutex オブジェクトにも適用されますか。特定の関数でロックおよびロック解除される親にミューテックスがあるとします。ここで、親プロセスが子プロセスを作成します。親と子の両方がこの関数を同時に呼び出すことができます (親はマルチスレッド プログラムであるため、子が終了するまで親は実際にはブロックされません。子を生成するスレッドは 1 つだけブロックされます)。では、mutex オブジェクトの状態は 2 つのプロセス間で共有されているのでしょうか? 親でミューテックスがロックされていて、子が作成された場合、子が最初に実行されます子は、ミューテックス オブジェクトを親からそのまま継承したため、ミューテックスがロックされた状態になっていることがわかります。子はミューテックスをロック解除します。現在、親でのこのミューテックスの状態はどうですか- まだロックされている (親がロックを解除していないため)、または子供がロックを解除したためにロック解除されている。

親と子からグローバルミューテックスをロック/ロック解除するような関数を呼び出しても大丈夫ですか?

于 2009-09-25T08:20:05.503 に答える
0

はい、あなたの考えは正しいですが、メモリを節約するために、子が exec システムコールを実行するか、変数またはデータ構造のいずれかを変更するまで、内部的にページは親と子の間で共有されます。親と子.....ページが子によって変更された場合、そのページは別のメモリ領域にコピーされ、子に割り当てられます。親によって変更された場合、そのページは別のメモリ領域にコピーされます親に割り当てられます

于 2010-04-18T09:17:30.923 に答える