Jan*_*.Le 8 c unix fork copy-on-write
这是我的代码
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;
}
Run Code Online (Sandbox Code Playgroud)
该程序的输出如下:
before: 3 ffbff440
after: 30 ffbff440
father: 3 ffbff440
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么孩子和父母的变量的地址相同但价值不同?
pax*_*blo 25
因为它是虚拟地址,而不是物理地址.
每个进程都有自己的地址空间(例如,32位系统可能允许每个进程拥有自己的完整4G范围的地址空间).
它是内存管理单元,它将虚拟地址映射到物理地址(如果需要从二级存储中重新购买换出的页面,则处理诸如页面错误之类的内容).
下图可能有所帮助,每个部分代表4K内存块:
Process A Physical Memory Process B
+-------+ +-------------+ +-------+
0K | |----> 0K | (shared) | <----| | 0K
+-------+ +-------------+ +-------+
4K | |--+ 4K | | <----| | 4K
+-------+ | +-------------+ +-------+
8K | | +-> 8K | | | | 8K
+-------+ +-------------+ +-------+
| : : : : : : : |
| +-------------+ |
| 128K | | <--------+
| +-------------+
+--------> 132K | |
+-------------+
Run Code Online (Sandbox Code Playgroud)
您可以在该图中看到虚拟内存地址与物理内存地址之间的断开(以及进程共享内存块的可能性).左侧和右侧的地址是进程看到的虚拟地址.
中央块中的地址是数据"真实"的实际物理地址,MMU处理映射.
有关fork
(和exec
)的更深入解释,您可能还想看看这个答案.