关于fork系统调用和全局变量

lur*_*rks 2 c++ unix fork linux-kernel

我在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;
}
Run Code Online (Sandbox Code Playgroud)

两个分叉进程对共享变量进行增量,父进程执行相同操作.由于变量属于每个进程的数据段,因此最终值为10,因为增量是独立的.

但是,共享变量的内存地址是相同的,您可以尝试编译并观察程序的输出.怎么解释?我无法理解,我以为我知道fork()是如何工作的,但这看起来很奇怪..

我需要解释为什么地址是相同的,尽管它们是单独的变量.

Ale*_*lli 10

操作系统正在使用虚拟内存和类似技术来确保每个进程在同一地址看到不同的内存单元(虚拟或读取); 只共享显式共享的内存(例如通过shm),默认情况下所有内存在不同进程之间是分开的.


Mar*_*wis 7

这称为"虚拟地址".每个进程都有自己的地址空间,每个地址都意味着不同的东西,具体取决于进程.fork()创建一个副本,而不是共享数据(从技术上讲,它们可能会在写入时进行共享拷贝,但这与前期复制具有相同的效果).IOW,变量"shared"不在进程之间共享.