【问题标题】:why the values created before c++ fork function called not modified twice by the parent and child process?为什么在调用 c++ fork 函数之前创建的值没有被父进程和子进程修改两次?
【发布时间】:2021-02-10 11:47:54
【问题描述】:

不太明白下面C++程序的输出。

#include <iostream>
#include <sys/types.h>

void foo(int *p) {
  std::cout << p << std::endl;
  (*p) ++;
}

int main() {
  int i = 100;
  if (fork() == 0) {
    foo(&i);
    std::cout << i << std::endl;
  } else {
    foo(&i);
    std::cout << i << std::endl;
  }
}

样本输出可能是

0x10f273070
101
0x10f273070
101

为什么地址相同,输出都是101?我希望一个进程输出 101,另一个输出 102。

【问题讨论】:

  • 一个进程中的地址与另一个进程中的地址不同。它们仅在过程的上下文中有效。操作系统和 CPU 在内部将这些值映射到实际物理地址(使用进程上下文中的表)。此外,如果你 fork 一个进程,物理内存中的变量地址不会改变,除非你改变它们的值,此时会发生写时复制,并且从现在开始,一个 fork 进程中的变量物理地址将有所不同。
  • 谢谢!但有一件事是 fork 似乎创建了一个子进程并运行自身下面的代码。我可以理解您的意思,地址映射到两个进程的不同物理地址。但是它们怎么都具有 100 的值呢?他们将值从父进程使用的物理地址复制到子进程?
  • 分叉进程的物理内存是父进程的确切物理内存。没有复制。除非子级或父级更改值,此时,变量将被复制到新的物理内存位置,并且更改适用于这个新位置。

标签: c++ multiprocessing fork


【解决方案1】:

fork 上,子进程和父进程在不同的内存空间中运行。

  1. 因此您将在父进程和子进程中看到相同的数据
  2. 在两个进程中打印的地址都是虚拟地址,而不是物理地址

【讨论】:

  • 谢谢!但有一件事是 fork 似乎创建了一个子进程并运行自身下面的代码。我可以理解您的意思,地址映射到两个进程的不同物理地址。但是它们怎么都具有 100 的值呢?他们将值从父进程使用的物理地址复制到子进程?
  • 是的,详情请关注this。基本上整个进程内存被复制到子进程,因此所有变量值在分叉后保持不变。
【解决方案2】:

fork() 克隆一个子进程,它也克隆父进程的内存,因此子进程中的所有变量都具有与其父进程相同的逻辑地址和值。如果在fork() 之后更新变量,它只会更新自己进程的值。这就是为什么您看到两个打印件都是 101。

【讨论】:

    猜你喜欢
    • 2021-04-26
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    相关资源
    最近更新 更多