2010-01-28 11 views
8

non ci sto capendo l'output di questo programma:C forcella che fare con la variabile globale

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

int i = 0; 

int main() 
{ 
    while(i<3) 
    { 
     fork(); 

     printf("%d\n",i); 
     ++i; 
    } 
} 

L'output è:

0 
1 
2 
2 
1 
2 
0 
1 
2 
2 
2 
1 
2 
2 

Può per favore qualcuno mi dica come posso affrontare questo problema in per capire appieno perché sto ottenendo questo risultato?

+2

Non ci hai detto cosa non ti piace di questo. – bmargulies

+0

Non mi piace perché non capisco quando stiamo incrementando il fork sul processo padre o nei processi figli. Normalmente se vogliamo incrementare nel processo figlio lo facciamo se (fork() == 0) ++ i; ma quando facciamo una forchetta come questa, mi sento un po 'perso nel mezzo! – Bruno

+1

Come per ogni risposta: il bambino incrementa il figlio, il genitore incrementa il genitore, mai il twain lo farà. – bmargulies

risposta

24

Fork eseguirà una copia del processo. Una copia indipendente del processo. Quindi, se una variabile globale contiene 3 nel momento in cui si esegue il fork, ogni copia del processo ottiene il proprio valore 3. E se modificano, le loro modifiche sono completamente indipendenti.

3

Provare a utilizzare pthreads se si desidera creare un thread all'interno del processo per la programmazione simultanea. La funzione che desideri è pthread_create e pthread_join per riordinare in seguito.

Qualcosa di simile a questo:

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


int i = 0; 

void *threadFunc(void *arg) 
{ 
    printf("%d\n",i); 
} 

int main() 
{ 
    int j = 0; 
    int returnValue = 0; 
    pthread_t* myThread = (pthread_t*) calloc(3, sizeof(pthread_t));; 

    while(i < 3) 
    { 

     returnValue = pthread_create(&myThread[i], NULL, threadFunc, NULL); 
     printf("main thread: %d\n",i); 
     i++; 

    } 


    for(j = 0; j < 3; j++) 
    { 
     pthread_join(myThread[j], NULL); 

    } 

    return 0; 
} 

Ma forse no, a seconda delle proprie effettive esigenze.

5

Quando si esegue il fork(), viene creata una copia completa del processo corrente nel suo stato corrente. Ciò significa che il processo iniziale creerà tre nuovi processi che si trovano nel mezzo del ciclo while, con i che corrispondono rispettivamente a 0, 1 e 2 in ciascuno di essi. Inoltre stamperà i propri valori di i.

Ciascuno dei suoi figli continuerà il ciclo dalla chiamata fork() stampando il suo valore iniziale i, l'incremento e il ciclo. Ciò significa che i bambini 0 stamperanno 0, 1 e 2 e genereranno due nuovi figli, con valori "iniziali" di i 1 e 2. I bambini 1 stamperanno 1 e 2 e genereranno un altro bambino, con un valore "iniziale" di i su 2. Children 2 stamperà 2 e lascerà il ciclo.

Se continuate a ragionare, arriverete alla conclusione che verranno stampati in totale due 0, quattro 1 e otto 2. Tuttavia, poiché l'ordine di esecuzione dipende da come il sistema operativo pianifica i processi concorrenti, non è possibile avere garanzie sull'ordine in cui vengono stampati.

16

modificare il codice per questo e l'uscita dovrebbe rendere molto più senso:

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 

int i = 0; 

int main() 
{ 
    while (i < 3) 
    { 
     fork(); 
     printf("pid = %d, i = %d\n", getpid(), i); 
     ++i; 
    } 
    return 0; 
} 
2

E 'qualcosa di simile ...

1 (main) instance, i = 0(unforked) 
fork() > 2 instances, with i's = 0(forked), and 0(forked) 
0 output from main instance, increments its i, 2 instances with i = 1u, 0f 
main instance forks, there's 3 instances with i's 1f, 1f, 0f 
1 output from main instance, increments its i, 3 instances with i = 2u, 1f, 0f 
main instance forks, there's 4 instances with i's 2f, 2f, 1f, 0f 
2 output from main instance, increments its i, 4 instances with i = 3u, 2f, 1f, 0f 
main instance then dies, 3 instances with i = 2f, 1f, 0f 
2 output from next instance, increments its i, 3 instances with i = 3u, 1f, 0f 
next instance then dies, 2 instances with i = 1f, 0f 
1 output from next instance, increments its i to 2, 2 instances with i = 2u, 0f 

... ecc

L'ordine che i processi in uscita, tuttavia, sono indeterminati, quindi probabilmente non vedrai lo stesso identico output ogni volta, e anche se lo fai non è qualcosa che puoi garantire.

Come hanno detto altre persone, ogni processo ha una propria "i" globale di cui tiene traccia e il suo valore è semplicemente il valore del processo di forking al bivio.