2015-09-24 23 views
5

İşte kod:Neden fork() aynı değişkeni ancak farklı değeri kullanıyor?

#include <stdio.h>                                        
#include <unistd.h> 

void f(int&); 
void g(int&); 

int main(int argc, char **argv) 
{ 
    printf("--beginning of program\n"); 

    int counter = 0; 
    pid_t pid = fork(); 
    if (pid == 0) { 
     f(counter); 
     printf("child process: %d, %p", counter, &counter); 
    } else if (pid>0) { 
     g(counter); 
     for (int i=0; i<5; ++i) { 
      sleep(1); 
      printf("parent process: %d, %p\n", counter, &counter); 
     } 
    } 
    printf("--end of program--\n"); 
    return 0; 
} 

void f(int& counter) { 
    counter = 1; 
    printf("in f: %d, %p-\n", counter, &counter); 
} 
void g(int& counter){ 
} 

İşte sonuç:

--beginning of program 
in f: 1, 0x7ffc9b01c6a4- 
child process: 1, 0x7ffc9b01c6a4--end of program-- 
parent process: 0, 0x7ffc9b01c6a4 
parent process: 0, 0x7ffc9b01c6a4 
parent process: 0, 0x7ffc9b01c6a4 
parent process: 0, 0x7ffc9b01c6a4 
parent process: 0, 0x7ffc9b01c6a4 
--end of program-- 

Açıkça çocuk sürecinde aynı adrese sahip aynı parametre, ama değer farklıdır.

Neden oluyor ?

+9

Yanlış olduğunuzda "açıkça" gibi terimlerden kaçınmaya çalışın;) –

cevap

10

Her süreç kendi sanal bellek alanını sahiptir. Bir işlemde 0x7ffc9b01c6a4 anlamına

başka 0x7ffc9b01c6a4 tamamen ilgili değildir.

Bu aynı nesne değildir; Yeni süreçte bir nesne. İkinci süreç, birinciden esinlenerek, esasen sürecin klonlanması, nesnelerin, saniyeler içinde olduğu gibi, aynı sanal bellek konumunda bulunması bir sürpriz değildir.

3

Bu, fork()'un temelidir ve bu, tam olarak çalışmasına izin veren şeydir. Bunu anlamak için, modern işletim sistemlerinde sürecin tüm adres alanlarının sanal olduğunu unutmayın; bu, gerçek fiziksel bellek adresleriyle hiçbir ilgisi yoktur. Gitti, 0x8000 adresindeki belleğe erişimin (adresi doğru hatırlıyorum) doğrudan video belleğine gittiği günler. Bu şekilde program yapardım ve ekran manipülasyon rutinleri yerine video belleğindeki değerleri yazdı, ki bu daha hızlıydı. Bu :)

eğlenceliydi Ama artık yok. Şimdi kullanıcı programlarında adres fiziksel bellek ile hiçbir ilgisi yoktur ve ne zaman '0x1234567' adresindeki belleğe eriştiğinizde çeviri yapılır. CPU bu sanal adresi fiziksel bellek adresine nasıl eşleyeceğini biliyor, ancak başka hiçbir şey yapmıyor.

Bu nedenle, işleminizi çatalladığınızda, tam bir bellek kopyası yapılır. Aynı sanal adreslere sahip (çünkü bellek çoğaltma kesin!). Ancak şimdi bir fark süreci olduğundan, CPU bu sanal adresleri farklı fiziksel hafıza adreslerine çevirecektir. En azından, bu semantik. Gerçek Modern sistemlerde, tam bellek çoğaltma gerçekten — veya fork() çok uzun sürer oluyor olmayacaktır. Bunun yerine, bellek 'üzerine yazma' olarak işaretlenir. Demek ki, veriler değiştirilinceye kadar, iki işlemci aynı fiziksel belleğe erişecek. Ancak herhangi bir süreç hafızayı değiştirir düzeltmez, aslında kopyalanacak ve şimdi herkes kendi kopyalarına sahip olacak.

+0

COW hakkında iyi nokta. Tabii ki, hatta kopya sonra, adresi aynı :) –

+0

@LightnessRacesinOrbit _still_ olur, SANAL adres elbette aynı olacaktır. – SergeyA

+0

OP tarafından görülen adres evet. –

İlgili konular