为啥在调用 c++ fork 函数之前创建的值没有被父进程和子进程修改两次?
Posted
技术标签:
【中文标题】为啥在调用 c++ fork 函数之前创建的值没有被父进程和子进程修改两次?【英文标题】: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 的值呢?他们将值从父进程使用的物理地址复制到子进程? 分叉进程的物理内存是父进程的确切物理内存。没有复制。除非子级或父级更改值,此时,变量将被复制到新的物理内存位置,并且更改适用于这个新位置。 【参考方案1】:在fork 上,子进程和父进程在不同的内存空间中运行。
-
因此您将在父进程和子进程中看到相同的数据
在两个进程中打印的地址都是虚拟地址,而不是物理地址
【讨论】:
谢谢!但有一件事是 fork 似乎创建了一个子进程并运行自身下面的代码。我可以理解您的意思,地址映射到两个进程的不同物理地址。但是它们怎么都具有 100 的值呢?他们将值从父进程使用的物理地址复制到子进程? 是的,详情请关注this。基本上整个进程内存被复制到子进程,因此所有变量值在分叉后保持不变。【参考方案2】:fork()
克隆一个子进程,它也克隆父进程的内存,因此子进程中的所有变量都具有与其父进程相同的逻辑地址和值。如果在fork()
之后更新变量,它只会更新自己进程的值。这就是为什么您看到两个打印件都是 101。
【讨论】:
以上是关于为啥在调用 c++ fork 函数之前创建的值没有被父进程和子进程修改两次?的主要内容,如果未能解决你的问题,请参考以下文章