2012-03-15 133 views
5

我是「fork()」的新手,我在任何地方都會看到,當fork()被調用時,當前(調用)過程的精確副本已經啓動。現在,當我運行下面的代碼時,應該有兩個不同的過程,兩個不同的存儲位置分配給他們的變量和功能。使用fork時如何映射內存?

#include<stdio.h> 
int i=10; 
int pid; 
int main(){ 
    if((pid=fork())==0){ 
    i++;//somewhere I read that separate memory space for child is created when write is needed 
    printf("parent address= %p\n",&i);// this should return the address from parent's memory space 
    }else{ 
    i++; 
    i++; 
    printf("child address= %p\n",&i);// this should return the address of child's memory space 
    } 
    wait(0); 
    return(0); 
} 
 
Why The output looks like:: 
child address::804a01c 
parent address::804a01c 

爲什麼這兩個地址是家長以及孩子一樣嗎?

+4

他們*最好*是一樣的。您希望指針在兩個進程中以相同的方式引用內存(即使兩個內存塊都不同)。閱讀*虛擬內存*,這將回答你的問題。 – 2012-03-15 17:00:58

+1

請注意,即使兩個副本都存儲在相同的虛擬地址,父節點與子節點之間的'i'的*值*也是不同的。 – markgz 2012-03-15 18:19:54

回答

8

將兩個不同的存儲位置分配給它們的變量和函數。

都能跟得上; Linux實現了virtual memory,這意味着每個進程都有自己的完整地址空間。因此,在fork之後,兩個進程都會爲其內存對象的副本查看相同的地址。

+4

「旁邊」實際上非常重要:當孩子進程被引發時,沒有任何東西真的被複制。考慮到分叉在Unix上經常發生(幾乎每次你產生一個新的進程),這將會是一個巨大的性能損失。確切的機制依賴於「頁面錯誤」。如果你有興趣,你可能想閱讀它們。 – 2012-03-15 17:04:09

+0

好的,那麼我們如何才能得到該虛擬變量的實際地址而不是虛擬地址?(只是爲了滿足我的好奇心) – buch11 2012-03-15 17:05:52

+1

@ buch11:我認爲你不能,但我會讓專家確認。無論如何,你不應該。這種信息只被內核知道,它只會讓你訪問進程本地地址。這被稱爲「受保護的內存」。每個進程只能訪問自己的內存。 – 2012-03-15 17:10:25

2

地址是處理本地(順便VM還導致將在物理內存中的過程之間共享代碼,所有的數據將只copied-on-write)。 804a01c在另一個過程中與804a01c不同。

2

由於virtual memory:兩個地址空間看起來都與各個進程相同。這些存儲的物理內存是不同的。然而,實際上,由內存優化(由大多數內核實現)使其複雜化,其將相應的不同虛擬頁面映射到相同的物理頁面,直到這些進程中的一個寫入該內存頁面,此時該頁面被物理地複製到另一個物理地址(並且虛擬頁面爲該過程重新映射)。

還有很多其他的複雜情況:最被認可的是fork()的返回值在進程間是不同的,儘管這通常是寄存器值的差異,而不是內存。但是,打開的文件和其他一些資源可能被標記爲不可繼承,因此可能存在其他不同之處,但有時可用。