Saltar al contenido

Python: ¿Cómo funciona os.fork()?

La guía o código que hallarás en este artículo es la resolución más fácil y válida que encontramos a esta inquietud o dilema.

Solución:

En primer lugar, elimina eso print '******...' línea. Simplemente confunde a todos. En su lugar, probemos este código…

import os
import time

for i in range(2):
    print("I'm about to be a dad!")
    time.sleep(5)
    pid = os.fork()
    if pid == 0:
        print("I'm , a newborn that knows to write to the terminal!".format(os.getpid()))
    else:
        print("I'm the dad of , and he knows to use the terminal!".format(pid))
        os.waitpid(pid, 0)

Bien, antes que nada, ¿qué es “fork”? Tenedor es una característica de los sistemas operativos modernos y compatibles con los estándares (excepto M$ Windows: esa broma de un sistema operativo es casi moderna y compatible con los estándares) que permite un proceso (también conocido como: “programa”, ¡y eso incluye el intérprete de Python! ) para hacer literalmente un duplicado exacto de sí mismo, creando efectivamente un nuevo proceso (otra instancia del “programa”). Una vez hecha esa magia, ambos procesos son independientes. Cambiar cualquier cosa en uno de ellos no afecta al otro.

El proceso responsable de deletrear este encantamiento oscuro y antiguo se conoce como el proceso padre. El resultado sin alma de esta abominación inmoral hacia la vida misma se conoce como el proceso del niño.

Como resultará evidente para todos, incluidos aquellos para los que no lo es, puedes formar parte de ese selecto grupo de programadores que han vendido su alma a través de os.fork(). Esta función realiza una operación de bifurcación y, por lo tanto, da como resultado la creación de un segundo proceso de la nada.

Ahora, ¿qué devuelve esta función, o más importante, cómo ¿incluso regresa? Si quieres no volverte loco, por favor no vayas a leer el kernel de Linux /kernel/fork.c ¡expediente! Una vez que el núcleo hace lo que sabemos que tiene que hacer, pero no queremos aceptarlo, os.fork() regresa en los dos procesos! Sí, ¡incluso se copia la pila de llamadas!

Entonces, si son copias exactas, ¿cómo se diferencia entre padre e hijo? Sencillo. Si el resultado de os.fork() es cero, entonces estás trabajando en el niño. De lo contrario, está trabajando en el padre y el valor de retorno es el PID (IDentificador de proceso) del hijo. De todos modos, el niño puede obtener su propio PID de os.getpid()¿no?

Ahora, tomando esto en cuenta, y el hecho de que hacer fork() dentro de un bucle está la receta para el desorden, esto es lo que sucede. Llamemos al proceso original el proceso “maestro”…

  • Maestría: i = 0se bifurca en child-#1-of-master
    • Niño-#1-del-maestro: i = 1 se bifurca en niño-#1-de-niño-#1-de-maestro
    • Niño-#1-de-niño-#1-de-maestro: for bucle, salidas
    • Niño-#1-del-maestro: for bucle, salidas
  • Maestría: i = 1se bifurca en child-#2-of-master
    • Niño-#2-del-maestro: i = 1 se bifurca en niño-#1-de-niño-#2-de-maestro
    • Niño-#1-de-niño-#2-de-maestro: for bucle, salidas
    • Niño-#2-del-maestro: for bucle, salidas
  • Maestría: for bucle, salidas

Como puede ver, hay un total de 6 impresiones padre/hijo provenientes de 4 procesos únicos, lo que da como resultado 6 líneas de salida, algo así como…

¡Soy el papá de 12120 y él sabe usar la terminal!

¡Soy 12120, un recién nacido que sabe escribir en la terminal!

¡Soy el papá de 12121 y él sabe usar la terminal!

¡Soy 12121, un recién nacido que sabe escribir en la terminal!

¡Soy el papá de 12122 y él sabe usar la terminal!

¡Soy 12122, un recién nacido que sabe escribir en la terminal!

Pero eso es arbitrario, podría haber generado esto en su lugar …

¡Soy 12120, un recién nacido que sabe escribir en la terminal!

¡Soy el papá de 12120 y él sabe usar la terminal!

¡Soy 12121, un recién nacido que sabe escribir en la terminal!

¡Soy el papá de 12121 y él sabe usar la terminal!

¡Soy 12122, un recién nacido que sabe escribir en la terminal!

¡Soy el papá de 12122 y él sabe usar la terminal!

O cualquier otra cosa que no sea eso. El sistema operativo (y los relojes funky de su placa base) es el único responsable del orden en que los procesos obtienen intervalos de tiempo, así que culpe a Torvalds (y no espere tener autoestima cuando regrese) si no le gusta cómo el kernel logra organizar sus procesos ;).

¡Espero que esto te haya dado algo de luz!

Para responder a la pregunta directamente, os.fork() funciona llamando a la función del sistema operativo subyacente fork().

Pero seguramente estás interesado en lo que esto hace. Bueno, esto crea otro proceso que se reanudará exactamente en el mismo lugar que este. Entonces, dentro de la primera ejecución del ciclo, obtiene una bifurcación después de la cual tiene dos procesos, el “original” (que obtiene un pid valor del PID del proceso hijo) y el bifurcado (que obtiene un pid valor de 0).

Ambos imprimen su pid value y continuar con la segunda ejecución del bucle, que ambos imprimen. Luego ambos se bifurcan, dejándote con 4 procesos que imprimen sus respectivos pid valores. Dos de ellos deben ser 0los otros dos deben ser los PID del niño que acaban de crear.

Cambiando el código a

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import time

for i in range(2):
    print '**********%d***********' % i
    pid = os.fork()
    if pid == 0:
        # We are in the child process.
        print "%d (child) just was created by %d." % (os.getpid(), os.getppid())
    else:
        # We are in the parent process.
        print "%d (parent) just created %d." % (os.getpid(), pid)

verás mejor lo que pasa: cada proceso te dirá su propio PID y lo que pasó en la bifurcación.

Si te gustó nuestro trabajo, puedes dejar un artículo acerca de qué te ha gustado de este post.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *