fork 后的变量

Variables after fork

这是一个代码:

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

程序打印你好,世界!有一次,子进程不是从头开始的,也不是重新定义变量。变量地址相同。所以他们是一样的。但是我改变了我在先执行的父进程中的值,它并没有改变子进程。为什么?

当您执行 fork() 时,将创建包括变量在内的整个流程。所以 parent 中的 i 不是 child 中的 i。它们具有相同的虚拟地址但不相同的物理地址。修改完全独立

Adresses of variables are same. So they are same. But I change i's value in parent process which is executed first, it didn't change for child process. Why?

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

来自 man page for fork:

On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.

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

if(pid) 计算结果为 if(true)

并且它将执行 parent。然而,child 将 0 分配给 pid(这就是它知道它是 child 的方式)。

if(0) 的计算结果为 if(false)

因此 i 的值不会改变。

但是,由于抽象,进程在 虚拟地址 中看到内存(虚拟地址 space 完全 复制了fork)。只有内核可以管理物理地址,并且进程与内核通信以获取此内存(进程只是说 "put this variable i at this address: 0x7fffc2490278" 并且内核基本上会将其映射到它想要的任何位置)。就进程所知,它是唯一需要内存的进程,这就是为什么它们的地址是 "same".

变量存在于进程的虚拟地址space中。进程的地址 space 是该进程的本地地址。您在两个处理中看到相同地址的事实并不意味着您正在访问相同的变量。完全没有。

地址值仅在其自身进程的上下文中才有意义。比较来自不同进程地址 spaces.

的地址是没有意义的

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