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.
@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
¡excelente respuesta! –
En su ejemplo 'el valor de b = 0 // parent'. ¿Debería leer esto 'el valor de b = 0 // niño' en su lugar? – srkrish