Operating system 为什么在fork()系统调用中修改后变量的地址保持不变

Operating system 为什么在fork()系统调用中修改后变量的地址保持不变,operating-system,Operating System,考虑以下代码片段 if (fork() == 0) { a = a + 5; printf("%d, %d \n", a, &a); } else { a = a - 5; printf ("%d, %d \n", a,& a); } 好的,当创建fork()时,父级的虚拟地址空间将复制到子级,并且子级和父级共享相同的物理页,直到其中一个尝试修改为止。当子级和父级中的一个修改变量时,父级的物理页面将复制到子级的另一个页面,并且物理页面保持

考虑以下代码片段

if (fork() == 0)
{
     a = a + 5;
     printf("%d, %d \n", a, &a);
}
else
{
     a = a - 5;
     printf ("%d, %d \n", a,& a);
}
好的,当创建fork()时,父级的虚拟地址空间将复制到子级,并且子级和父级共享相同的物理页,直到其中一个尝试修改为止。当子级和父级中的一个修改变量时,父级的物理页面将复制到子级的另一个页面,并且物理页面保持私有。
所以,这里“a”的值在子级和父级中是不同的。但当涉及到子级和父级中“a”的地址时,输出是相同的。我无法理解为什么即使物理页面不同,地址仍然保持不变

a的地址不是实际的物理地址

它是一个虚拟地址。
硬件/操作系统层将虚拟地址映射到物理地址(不可见地映射到应用程序)

因此,即使地址具有相同的
编号
,它们也不会映射到ram芯片上的相同物理内存


注:当使用printf()打印地址(即指针)时,最好使用“%p”

答案几乎在您的问题中:修改
a
后,会复制
a
的物理页(因此与父进程中的不一样),但会复制虚拟地址(通过
&a
您的程序可以看到什么)不会改变

事实上,在为
a
分配新值时,更改其虚拟地址将非常棘手。考虑一下,如果您以前存储了一个指向<代码>的指针< < /代码>:

 int *p = &a;
 a = a - 5;
 printf("%d", *p)
在第二行之后,p将不再指向
a
,这是任何程序员都不会想到的行为


对物理页的写入使用是对与程序行为无关的OS的优化:您可以考虑在叉时复制整个地址空间。

这意味着我们所看到的都是虚拟地址。我们可以通过我们的程序看到实际的物理地址吗?如果你得到正确的(操作系统)工具。但在正常情况下不会。