it-swarm-es.tech

Después de fork (), ¿dónde comienza su ejecución el niño?

Estoy tratando de aprender programación UNIX y encontré una pregunta con respecto a fork (). Entiendo que fork () crea un proceso idéntico al proceso que se está ejecutando actualmente, pero ¿dónde comienza? Por ejemplo, si tengo código

int main (int argc, char **argv)
{
    int retval;
    printf ("This is most definitely the parent process\n");
    fflush (stdout);
    retval = fork ();
    printf ("Which process printed this?\n");

    return (EXIT_SUCCESS);
}

El resultado es:

Este es definitivamente el proceso principal
¿Qué proceso imprimió esto?
¿Qué proceso imprimió esto?

Pensé que fork() crea un mismo proceso, así que inicialmente que en ese programa, la llamada fork() se llamaría recursivamente para siempre. Supongo que el nuevo proceso creado a partir de fork() comienza después de la llamada fork()?

Si agrego el siguiente código, para diferenciar entre un proceso primario y secundario,

if (child_pid = fork ()) printf ("This is the parent, child pid is %d\n", child_pid);
else printf ("This is the child, pid is %d\n",getpid ());

después de la llamada fork (), ¿dónde comienza su ejecución el proceso hijo?

22
thomas1234

El nuevo proceso se creará dentro de la llamada fork(), y comenzará regresando como el padre. El valor de retorno (que almacenó en retval) de fork() será:

  • 0 en el proceso hijo
  • El PID del niño en el proceso padre
  • -1 en el padre si hubo un fallo (no hay hijo, naturalmente)

Su código de prueba funciona correctamente; almacena el valor de retorno de fork() en child_pid y usa if para verificar si es 0 o no (aunque no busca un error)

23
Michael Mrozek

Pensé que fork () crea un mismo proceso, así que inicialmente que en ese programa, la llamada fork () se llamaría recursivamente para siempre. ¿Supongo que el nuevo proceso creado a partir de fork () comienza después de la llamada fork ()?

Si. Numeremos las líneas:

int main (int argc, char **argv)
{
    int retval;                                               /* 1 */
    printf ("This is most definitely the parent process\n");  /* 2 */
    fflush (stdout);                                          /* 3 */
    retval = fork ();                                         /* 4 */
    printf ("Which process printed this?\n");                 /* 5 */
    return (EXIT_SUCCESS);                                    /* 6 */
}

El flujo de ejecución es:

caller process     fork() → ...
                          ↘
original program            exec() → 2 → 3 → 4 → 5 → 6
                                               ↘
forked program                                   5 → 6

... que explica exactamente la salida que recibió.

Si desea saber cómo el programa original y el bifurcado pueden comportarse de manera diferente, ya que necesariamente comparten el mismo código, vea Respuesta de Michael Mrozek

13
badp

La verdadera solución a esto es

switch (fork()) {
    case -1 :
        fprintf (stderr, "fork failed (%s)\n", strerror(errno));
        break;
    case 0 :  // child process comes here
        break;
    default : // parent process
        break;
}

// all continue here
0
ott--