10

这是我的代码

int main()
{
  pid_t pid;
  int y = 3;  
  if ( (pid = fork()) <0 )
   return -1;;

  if( pid == 0 )  /* child */
  {
    printf(" before: %d %p\n", y, &y );
    y *= 10;
    printf("after: %d %p\n", y, &y );
  }
  else /* father */
  {
   sleep(1);
   printf("father: %d %p\n" , y , &y );

  }
  return 0;
}

程序的输出如下:

before: 3 ffbff440
after: 30 ffbff440
father: 3 ffbff440

我的问题是为什么孩子和父母的变量地址相同但值不同?

4

2 回答 2

27

因为它是虚拟地址,而不是物理地址。

每个进程都有自己的地址空间(例如,32 位系统可能允许每个进程拥有自己的地址空间,其完整的 4G 范围)。

它是内存管理单元,它将虚拟地址映射到物理地址(如果需要从辅助存储买回换出的页面,则处理页面错误之类的事情)。

下图可能会有所帮助,每个部分代表一个 4K 内存块:

   Process A           Physical Memory      Process B
   +-------+           +-------------+      +-------+
0K |       |---->   0K |  (shared)   | <----|       | 0K
   +-------+           +-------------+      +-------+
4K |       |--+     4K |             | <----|       | 4K
   +-------+  |        +-------------+      +-------+
8K |       |  +->   8K |             |      |       | 8K
   +-------+           +-------------+      +-------+
       |                : : : : : : :           |
       |               +-------------+          |
       |          128K |             | <--------+
       |               +-------------+
       +--------> 132K |             |
                       +-------------+

您可以在该图中看到虚拟内存地址和物理内存地址之间的断开连接(以及进程共享内存块的可能性)。左右两侧的地址是进程看到的虚拟地址。

中央块中的地址是数据“真正”所在的实际物理地址,MMU 处理映射。

有关fork(and exec) 的更深入解释,您可能还想查看这个答案

于 2011-08-31T07:14:03.840 回答
1

地址是“相同的”,因为每个进程都有自己的虚拟地址空间,并且变量通常会加载到相同的位置。请注意,这不是内存中的物理地址。另请注意,有些方案会故意随机化进程加载的位置,以使其更难攻击/破解进程。在这种情况下,地址将不同。

于 2011-08-31T07:10:58.643 回答