【问题标题】:About fork system call and global variables关于 fork 系统调用和全局变量
【发布时间】:2010-11-18 04:07:19
【问题描述】:

我有这个 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;
}

两个分叉的进程对共享变量进行增量,父进程也这样做。由于该变量属于每个进程的数据段,所以最终值为10,因为增量是独立的。

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

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

【问题讨论】:

  • 记住 fork 在写入时会进行复制,因此在您更改 var 之前它在所有进程中都是相同的
  • 它不能以任何其他方式工作,否则你的指针将在分叉后失效。不是很有用...

标签: c++ unix linux-kernel fork


【解决方案1】:

是的,您认为是正确的,但是为了节省一些内存,页面在内部由父级和子级共享,直到子级执行 exec 系统调用或修改任何变量或数据结构。因为许多页面在父子之间共享.....如果页面被子修改,则该页面将复制到单独的内存区域并分配给子。如果它被父修改,则该页面将被复制到单独的内存区域并分配给父级

【讨论】:

    【解决方案2】:

    这是否也适用于 pthread_mutex 对象。假设我在父级中有互斥锁,它在特定函数中被锁定和解锁。现在父进程创建一个子进程。父母和孩子都可以同时调用这个函数(父母直到孩子退出才真正被阻塞,因为父母是一个多线程程序,产生孩子的线程只有一个被阻塞)。 那么互斥对象状态是否在两个进程之间共享? 如果在父母身边, 互斥锁被锁定 然后创建了孩子 孩子先跑 孩子看到互斥锁处于锁定状态,因为它刚刚从父级继承了互斥锁对象 现在孩子解锁互斥锁 现在父级中此互斥锁的状态如何 - 仍处于锁定状态(因为父级从未解锁)或已解锁,因为子级已将其解锁。

    是否可以调用这样的函数来锁定/解锁来自父母和孩子的全局互斥锁?

    【讨论】:

      【解决方案3】:

      这称为“虚拟地址”。每个进程都有自己的地址空间,每个地址的含义不同,具体取决于进程。 fork() 创建一个副本,而不是共享数据(从技术上讲,它们可能会在写入时共享副本,但这与预先复制的效果相同)。 IOW,变量“shared”不在进程之间共享。

      【讨论】:

        【解决方案4】:

        现代系统上的指针与实际的硬件内存地址不对应。相反,地址映射到由操作系统管理的虚拟空间。因此,两个不同进程的指针地址可能看起来相同,但实际上它们并不相同。

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 2018-06-15
            • 2023-03-14
            • 1970-01-01
            • 2011-01-10
            • 1970-01-01
            • 2013-10-24
            • 2013-10-09
            • 2011-10-03
            • 1970-01-01
            相关资源
            最近更新 更多