2010-01-28 36 views
8

No estoy comprensión de la salida de este programa:C tenedor frente a la variable global

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

int i = 0; 

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

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

La salida es:

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

se puede complacer a alguien que me diga cómo debería abordar esta cuestión en para entender completamente por qué estoy obteniendo esta salida?

+2

No nos ha dicho lo que no le gusta de esto. – bmargulies

+0

No me gusta porque no entiendo cuando estamos incrementando el tenedor en el proceso principal o en los procesos de los niños. Normalmente, si queremos incrementar el proceso hijo hacemos if (fork() == 0) ++ i; pero cuando hacemos un fork así, ¡me pierdo un poco en el medio! – Bruno

+1

Según la respuesta: el niño aumenta el hijo, el padre incrementa el padre, nunca el segundo hijo meed. – bmargulies

Respuesta

24

Tenedor hará una copia del proceso. Una copia independiente del proceso. Entonces, si una variable global contiene 3 en el momento en que se bifurca, cada copia del proceso obtiene su propia 3. Y si se modifican, sus modificaciones son completamente independientes.

3

Trate de usar pthreads si desea crear un hilo dentro del proceso para la programación concurrente. La función que desea es pthread_create y pthread_join para ordenarla más tarde.

Algo como esto:

#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; 
} 

Pero tal vez no, dependiendo de sus necesidades reales.

5

Cuando tenedor(), una copia completa del proceso actual se crea en su estado actual. Esto significa que su proceso inicial creará tres nuevos procesos que se encuentran en el medio del ciclo while, con i siendo respectivamente 0, 1 y 2 en cada uno de ellos. También imprimirá sus propios valores de i.

Cada uno de sus elementos secundarios continuará el ciclo desde la llamada fork() imprimiendo su valor inicial i, incrementándose y creando un bucle. Esto significa que los niños 0 imprimirán 0, 1 y 2, y engendrarán dos niños nuevos, con valores "iniciales" de i 1 y 2. Los niños 1 imprimirán 1 y 2 y engendrarán un niño más, con un valor "inicial" de i de 2. Los niños 2 imprimirán 2 y abandonarán el ciclo.

Si sigue este razonamiento se llega a la conclusión de que un total de dos 0 de, se imprimirán de cuatro de las ocho 1 y 2. Pero, dado que el orden de ejecución depende de cómo el sistema operativo programa los procesos concurrentes, no puede tener garantías en el orden en que se imprimen.

16

cambiar el código para esto y la salida debe hacer mucho más sentido:

#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

Es algo así como ...

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 

... etc

El orden en que Sin embargo, los procesos están generando resultados indeterminados, por lo que es probable que no veas el mismo resultado cada vez, e incluso si lo haces no es algo que puedas garantizar.

Como se ha dicho otras personas, cada proceso tiene su propio mundial 'i' que rastrea, y su valor es simplemente el valor de i del proceso de bifurcación en el tenedor.