很明显我们有像
这样的代码块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;
}
每个printf()打印的地址都是相同的,因为这个主题的前一个post表明它是因为虚拟内存。但我的困惑是,这意味着每个父母和孩子都拥有单独的身体地址空间,如果是,则为什么虚拟地址不能不同,最终它将被MMU映射到相应的物理地址空间。
答案 0 :(得分:2)
因为那时你必须调整每个指针没有任何有用的理由。由于每个进程的程序相同,因此必须使用相同的虚拟地址才能工作。当然,使用动态分配时,即使虚拟地址也可能不同。
答案 1 :(得分:1)
是的,每个单独的进程都拥有自己的物理内存部分,即使虚拟地址可能会发生冲突,即使经常执行像写时复制这样的优化技术。
大多数现代实现都使用copy-on-write,这意味着在其中一个进程尝试修改内存之前,两个进程都将引用相同的物理内存。
在您的特定情况下,它意味着y
应该在子进程通过乘以它来修改它之前引用两个进程中的同一块物理内存。此时,内核将复制y
所在的整个页面,以便两个进程现在引用不同的物理内存块。
答案 2 :(得分:0)
您在此处使用&y
打印的是虚拟地址。它们可以是不同的,但对于分叉的子进程,它们与父进程中的进程相同是有意义的。
但另一方面,父母和孩子的实际地址不同。这就是为什么值仍然相同,即使在乘法之后。