2011-06-02 33 views
11

Ahora tengo un problema en la comprensión del funcionamiento de fork() llamada al sistema. escribo un código que está siguiendo:de trabajo de tenedor en lenguaje C

#include<stdio.h> 
int main() 
{ 
    int a, b; 
    b=fork(); 

    printf("\n the value of b = %d",b); 
} 

La salida de este código se siguiente:

Ahora bien, no entiendo por qué la salida es así?

Después de que acabo de añadir una línea en mi código y la salida es completamente diferente. mi código es el siguiente:

int main() 
{ 
    int a, b; 
    b=fork(); 

Cuando corro el código de la salida está siguiendo nombre 2389my es Manish

the value of b = 0 

Ahora estoy totalmente confundido sobre el funcionamiento de fork() llamada.

Mi pregunta son los siguientes:

  1. Cómo fork() obras?
  2. Cuando el control pasa después de la llamada fork()?
  3. ¿Puede algún cuerpo explicar por qué las salidas de códigos están escritas en el problema?
  4. Por qué la salida de b que ocurren en diferentes lugares significa en primer código la salida de b = 2260 es justo antes de la salida b = 0 mientras que el valor de b = 2389 no es justo antes de la b = 0?

Explícame el funcionamiento de la horquilla en el código escrito en el problema para que pueda aprenderlo correctamente.

Respuesta

5
  1. Fork crea una copia de su proceso actual.
  2. Tanto el original y la copia continuar con la ejecución desde el punto en el que se llamaba fork().
  3. Como su código se ejecuta dos veces, las instrucciones de impresión también se evalúan dos veces. En el proceso copiado, el valor de b es 0. En el proceso original, el valor de b es la ID del proceso copiado.
  4. Una vez que sus procesos se inician ejecutan al mismo tiempo, serán programadas de forma independiente por el sistema operativo y por lo tanto no cuentan con garantías sobre cuando en realidad se llevará a cabo.
3
  1. bifurca es implementado por el sistema operativo. Básicamente, crea un proceso hijo y comienza a ejecutarlo después del fork().

  2. El proceso principal recibe la identificación del proceso del proceso de archivo: b=fork(); b tiene la identificación del proceso. El proceso secundario obtiene un pid de cero.

  3. (y 4) Dado que ambos procesos pueden ejecutarse en paralelo o dividirse en tiempo, la salida variará.

Es posible que desee comprobar esto: http://en.wikipedia.org/wiki/Fork_(operating_system)

1

será mejor que empezar desde this.

Aquí encontrará ejemplos de explicación y código.

39

Podría ser útil entender primero por qué se usó la palabra fork para nombrar esta función. ¿Has oído hablar de un "tenedor en el camino"? En una bifurcación, el proceso tiene que dividir caminos.

Primero hay un único proceso que se ejecuta normalmente hasta que llega a la llamada fork. Cuando se llama a la horquilla, se crea un nuevo proceso, que es prácticamente idéntico en todos los sentidos al proceso original, , excepto por el valor de retorno de la función de la horquilla. El proceso recién creado se denomina proceso hijo y, por lo tanto, al proceso que lo generó se lo denomina proceso primario.

Dado que desea realizar diferentes tareas para cada rama de la bifurcación, es necesario que pueda distinguir el proceso hijo del proceso principal. Ahí es donde entra el valor de retorno de fork: fork devuelve el id. De proceso (pid) del hijo (el proceso recién creado) al padre; devuelve 0 al niño. Además, si la ejecución de fork falla, el valor de retorno es -1.

En su código, no distingue entre el proceso principal y secundario, por lo que ambos procesos ejecutan el código completo que sigue después de la llamada fork.

//what the child process looks like after fork is called 
int main() 
{ 
    int a, b; 
    b=fork(); // <-- current line of execution: 0 is returned to b 
    printf("\nmy name is manish\n"); 
    printf("\n my name is anil\n"); 
    printf("\n the value of b = %d",b); 
} 

// what the parent process looks like after fork is called 
int main() 
{ 
    int a, b; 
    b=fork(); // <-- current line: child process id is returned 
    printf("\nmy name is manish\n"); 
    printf("\n my name is anil\n"); 
    printf("\n the value of b = %d",b); 
} 

Como se puede ver, ambos procesos tienen el mismo código siguiente del tenedor, por lo tanto, la salida se repite. Tal vez si desea que el proceso padre a la salida Manish y el niño a la salida de Anil, entonces usted puede hacer algo como:

int main() 
{ 
    pid_t b; // note that the actual return type of fork is 
      // pid_t, though it's probably just an int typedef'd or macro'd 

    b = fork(); 
    if (b == -1) perror("Fork failed"); 
    else if (b > 0) { 
     printf("My name is Manish\n"); // parent process 
    else 
     printf("My name is Anil\n"); // child process 

    printf("The value of b is %d\n", b); 
    return 0; 
} 

Finalmente, el último comentario que debe hacerse es que en su código, la salida parece han sido ejecutados primero por un proceso en su totalidad y luego por el otro proceso en su totalidad. Ese no siempre es el caso. Por ejemplo, el sistema operativo puede permitir que el padre ejecute la salida 'manish', luego espere este proceso y entregue la CPU al proceso secundario, que luego ejecuta 'manish'. Sin embargo, el proceso hijo puede continuar y ejecutar las salidas 'anil' y 'b', completando la ejecución del proceso hijo y devolviendo así la ejecución al proceso padre. Ahora el padre termina su ejecución dando como salida 'anil' y 'b'. El resultado final de la ejecución de este programa puede ser algo como:

 
my name is manish  // executed by parent 
my name is anil  // child 
the value of b = 0 // child 
my name is anil  // parent 
the value of b = 2244 // parent 
[email protected]:~$ 

Tome un vistazo a la página del manual de fork. También vea waitpid para el manejo apropiado de procesos secundarios por procesos principales para que no cree zombies.

Editar: En respuesta a sus preguntas en los comentarios, responderé cómo puede simplemente ejecutar cada proceso consecutivamente.

int main() 
{ 
    pid_t pid; 
    int i; 

    for (i=0; i<NUM_PROCESSES; i++) 
    { 
     pid = fork(); 
     if (pid == -1) 
     { 
      perror("Error forking"); 
      return -1; 
     } 
     else if (pid > 0) 
     { 
      // parent process 
      waitpid(-1, NULL, 0); //might want to look at man page for this 
            // it will wait until the child process is done 
     } 
     else 
     { 
      // do whatever each process needs to do; 
      // then exit() 
      doProcess(i); 
      exit(0); 
     } 
    } 
    // do anything else the parent process needs to do 
    return 0; 
} 

Por supuesto, no es el mejor código, pero es sólo para ilustrar el punto. La gran idea aquí es la llamada waitpid, que hace que el proceso principal espere hasta que el proceso secundario solo fork ed termine.Una vez que se completa el proceso secundario, el elemento primario continúa después de la llamada waitpid, iniciando otra iteración del ciclo for y bifurcando otro (el siguiente) proceso. Esto continúa hasta que todos los procesos secundarios se hayan ejecutado secuencialmente y la ejecución finalmente regrese al padre.

+2

@Golu La idea de que se bifurcan estaba destinado para que los procesos pueden ejecutarse simultáneamente. Si quieres ejecutarlos en secuencia (lo que se puede hacer, sin decir que no pueden), ¿por qué molestarse en horquillas? ¿Hay un objetivo más grande que intenta lograr ejecutando los procesos en secuencia? – ladaghini

+0

¡excelente respuesta! –

+0

En su ejemplo 'el valor de b = 0 // parent'. ¿Debería leer esto 'el valor de b = 0 // niño' en su lugar? – srkrish