2011-12-02 94 views
4

其明顯,我們有一個代碼塊等父子地址空間混淆

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暗示的,其因爲虛擬memory.But我的困惑是,這是否意味着每個父母和孩子擁有單獨的物理地址空間,如果是,那麼爲什麼虛擬地址不能有所不同,因爲它最終將由MMU映射到相應的物理地址空間。

回答

1

是的,每一個獨立的進程擁有自己的物理內存的一部分,即使虛擬地址可能發生碰撞,即使優化技術,如寫入時複製經常進行。

大多數現代的實現使用寫入時複製,這意味着,直到過程中的一個試圖修改一塊內存,這兩個過程將是指相同的物理內存塊。

在您的特定情況下,它意味着y應該在兩個進程中引用同一塊物理內存,然後孩子通過將其與其相乘來修改它。此時,內核會複製整個頁面,其中y所在的位置使得這兩個進程現在引用不同的物理內存塊。

+0

好了,它表明,直到乘法的子進程的執行,無論是孩子和家長指向相同的物理地址和執行完成和最終值會修改,然後內核拷貝原有的物理地址空間,新的每一件事物理地址和現在的子地圖的虛擬地址。但是虛擬地址空間的相似性僅僅是爲了優化? –

+0

不,這是必須的:編譯後的程序使用虛擬內存地址來訪問變量(以及幾乎所有的東西)。這些是在編譯時確定的。 – Viruzzo

2

因爲那樣的話,你將不得不調整每一個指針沒有有用的原因。由於程序對於每個進程都是相同的,他們必須使用相同的虛擬地址才能工作。當然,即使使用動態分配,虛擬地址也可能會有所不同。

0

&y打印這裏什麼是虛擬地址。它們可以不同,但​​對於分叉子進程來說,它們與父進程中的相同。

但在另一邊,物理地址是家長和孩子的不同。這就是爲什麼數值仍然是相同的,即使在乘法之後。