2011-06-10 83 views
4

我对下面复制粘贴的程序有疑问。我在这里解释我对程序的理解:在这个程序中,父母创建一个孩子并等待它完成。然后,孩子创建一个线程并等待它完成。因此,变量''在子进程中的值为'5',在父进程中的值为'0',因为实际上有两个副本变量''值'其中一个在父级和其他在子项中(因为fork基本上是将父项的地址空间复制到子项)。然而,父母和孩子的变量''的地址都是相同的。我不明白如何。如果有人能解释这种行为,我将不胜感激。亲子子线程程序的奇怪行为

#include <stdio.h> 
#include <pthread.h> 


int value = 0; 
void *runner(void *param); 

int main() 
    { 
    int pid ; 
    pthread_t tid; 
    pthread_attr_t attr; 

    pid = fork(); 

    if(pid == 0) /* child */ 
     { 
     pthread_attr_init(&attr); 
     pthread_create(&tid, &attr, runner, NULL); 
     pthread_join(tid, NULL); 
     printf("CHILD: value = %d, address = %p\n", value, &value); 
     } 
    else if(pid > 0) /* Parent */ 
     { 
     wait(NULL); 
     printf("PARENT: value = %d, address = %p\n", value, &value); 
     } 
    } 

void *runner(void *param) 
    { 
    value = 5; 
    pthread_exit(0); 
    } 

回答

3

现代操作系统提供每个过程的虚拟地址空间,所以一致的地址并不意味着两个变量被存储在物理内存相同的目的地。

此外,大多数操作系统在分岔时使用写入时复制技术。这意味着父进程的地址空间的一部分不会复制到子进程的地址空间,直到子进程尝试更改它们。

+0

纠正我,如果我错了。虚拟地址不应该是唯一的吗? – 2011-06-10 13:56:14

+0

这可能意味着地址0xDEADBEEF将转换为任何两个进程的不同内存位置。 – 2011-06-10 13:58:24

+0

这是否意味着程序以某种方式打印偏移量?然后将其转换为物理地址? – 2011-06-10 14:03:59

1

桌面CPU和许多嵌入式CPU有一些称为内存管理单元(MMU)的东西。 MMU从虚拟地址转换为物理地址,因此每个进程都在自己的虚拟地址空间上运行,与其他进程分开。

MMU允许操作系统使用一些重要的技术,如按需分页,以及上述过程之间的分离。

fork()的高效实现需要使用MMU:正如您刚刚发现的,父进程和子进程使用相同的虚拟地址,但在不同的虚拟地址空间中,因此通常(忽略内存映射文件和共享内存)映射到不同的物理地址。