programa program metodo example c operating-system fork posix

c - program - Entender POSIX-tenedor()



metodo fork en c (2)

Estaba leyendo sobre la función de fork y cómo crea nuevos procesos. El siguiente programa funciona bien e imprime here dieciséis veces, pero tengo problemas para entender el flujo de ejecución:

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <limits.h> #include <sys/types.h> #include <unistd.h> #include <pthread.h> int main() { int i; for (i = 0; i < 4; i++) { // line no. 12 fork(); // line no. 13 } printf("%s/n", "here"); return 0; }

Me parece que hay dos formas en que este programa se puede ver como:

Primer enfoque: fork() se llama un total de cuatro veces. Si reemplazo el ciclo con cuatro llamadas a la función fork() , todo parece encajar y entiendo por qué here se imprime 2 ^ 4 veces.

Segundo enfoque: fork() genera un nuevo proceso exactamente desde donde se invoca y cada uno de estos procesos secundarios tiene sus propias variables locales. Entonces, después de la línea no. 13, cada uno de estos procesos hijo ve el final del ciclo ( } ) y van a la línea no. 12. Dado que todos estos procesos hijo tienen su propia variable local que establezco en 0 (¿tal vez se establece en algún valor de basura?), Todos se vuelven a bifurcar. Nuevamente para estos procesos secundarios, su variable local i se establece en 0. Esto debería resultar en una bomba de tenedor .

Ciertamente me falta algo en mi segundo enfoque, ¿podría alguien ayudarme?

Gracias.


Tu primer acercamiento fue correcto.
Esa es una respuesta bastante aburrida, así que le daré todos los detalles técnicos.

Cuando se llama fork , ocurren varias cosas:

  • Se crea un nuevo proceso (''el niño'')
  • La pila del padre se duplica y se asigna al niño.
  • El puntero de pila del elemento secundario se establece en el del elemento primario.
  • El PID (ID del proceso) del niño se devuelve al padre.
  • Zero se devuelve al niño

las variables declaradas dentro de una función se almacenan en la pila y, por lo tanto, comienzan en el mismo valor, pero no se comparten.
las variables declaradas fuera de una función (en el nivel superior) no están en la pila, por lo que se comparten entre el elemento secundario / principal.

(Algunas otras cosas están o no están duplicadas, vea man fork para más información).

Entonces, cuando ejecutas tu código:

what happens # of processes 1. the parent forks. 2 2. the parent and it''s child fork. 4 3. everyone forks 8 4. everyone forks 16 5. everyone prints "here". 16

Terminas con dieciséis procesos y la palabra "aquí" dieciséis veces.

básicamente,

if(fork() != 0) { parent_stuff(); } else { child_stuff(); }


Tu segundo enfoque no es correcto. Porque después de fork() el proceso secundario hereda el valor actual de i . No se establece en 0 cada vez que se llama fork() ni tiene valor de basura. Entonces, tu código no puede tener una bomba de tenedor. El hecho de que sea una variable local es irrelevante. fork() clona casi todo y el proceso hijo es idéntico a su padre, excepto por ciertas cosas como se indica en el manual de POSIX .

Reduciré el recuento de bucles a 2 para facilitar la explicación y asumir que todas las llamadas fork() tienen éxito:

for (i = 0; i < 2; i++) { fork(); } printf("%s/n", "here");

1) Cuando i=0 , se ejecuta fork() y ahora hay dos procesos. Llámalos P1 y P2.

2) Ahora, cada proceso P1 y P2 continúa con i = 0 el ciclo e incrementa i a 1. La condición for loop es verdadera, por lo que cada uno genera otros dos procesos y en total 4. Llámalos P1a & P1b y P2a & P2b. Los 4 procesos ahora tienen i = 1 y lo incrementan a 2 (a medida que continúan el ciclo).

3) Ahora, los 4 procesos tienen el valor de i como 2 y para la condición de ciclo es falso en todos ellos y "aquí" se imprimirá 4 veces (uno por cada proceso).

Si ayuda, puede convertir el bucle for en un bucle while y la forma en que se incrementa con ambos procesos que regresan de cada fork() puede ser un poco más claro:

i = 0; while(i < 2) { fork(); i++; } printf("%s/n", "here");