叉后的变量

这是一个代码:

int i=0; pid_t pid; puts("Hello, World!"); puts(""); pid = fork(); if(pid) i=42; printf("%p\n", &i); printf("%d\n", i); puts(""); 

并输出

 Hello, World! 0x7fffc2490278 42 0x7fffc2490278 0 

程序打印Hello,World! 有一次,所以子进程从一开始就没有开始,也没有重新定义变量。 变量的地址是相同的。 所以他们是一样的。 但是我在父进程中更改了i的值,它首先被执行,它对于子进程没有改变。 为什么?

变量的地址是相同的。 所以他们是一样的。 但是我在父进程中更改了i的值,它首先被执行,它对于子进程没有改变。 为什么?

地址属于流程范围。 它们是虚拟地址。 父进程中的地址0x7fffc2490278和子进程中的0x7fffc2490278是不同的物理地址。

当你执行fork() ,将创建包括变量的整个过程。 所以i在父母身边不是i的孩子。 它们具有相同的虚拟地址,但物理地址不同。 修改完全独立。

从fork的手册页 :

成功时,子进程的PID将在父进程中返回,并在子进程中返回0。 失败时,在父项中返回-1,不创建子进程,并正确设置errno。

也就是说,对于父pid被设置为大于0的数字(如果失败则为-1,你也应该检查)。

if(pid)求值为if(true)

它将为父母执行。 然而,孩子被分配到pid (这就是它知道它是孩子的​​方式)。

if(0)求值为if(false)

因此i的价值不会改变。

但是,由于抽象,进程看到虚拟地址中的内存(虚拟地址空间完全fork复制)。 只有内核可以管理物理地址,并且进程与内核通信以获取此内存(该过程只是说“将此变量i放在此地址: 0x7fffc2490278 ,内核将基本上将其映射到任何地方)。 就过程所知,这是唯一一个要求记忆的过程,这就是为什么他们的地址是“相同的”。

变量存在于进程的虚拟地址空间中。 进程的地址空间是该进程的本地空间。 您在两次处理中看到相同地址这一事实并不意味着您正在访问同一个变量。 一点也不。

地址值仅在其自身过程的上下文中才有意义。 比较来自不同进程的地址空间的地址是没有意义的。

父进程中的变量i与子进程中的变量i完全分离。 您只更改了一个i (父项的一个),这正是您在输出中观察到的内容。