ti-enxame.com

Após o fork (), onde a criança inicia sua execução?

Estou tentando aprender a programação do UNIX e me deparei com uma pergunta sobre fork (). Entendo que o fork () cria um processo idêntico ao processo em execução no momento, mas por onde começa? Por exemplo, se eu tiver 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);
}

A saída é:

Este é definitivamente o processo pai
Qual processo imprimiu isso?
Qual processo imprimiu isso?

Eu pensei que fork() cria o mesmo processo, então eu inicialmente que naquele programa, a chamada fork() seria chamada recursivamente para sempre. Eu acho que o novo processo criado a partir de fork() inicia após a chamada fork()?

Se eu adicionar o código a seguir, para diferenciar um processo pai e filho,

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 ());

após a chamada fork (), onde o processo filho inicia sua execução?

22
thomas1234

O novo processo será criado dentro da chamada fork() e começará retornando dela como o pai. O valor de retorno (que você armazenou em retval) de fork() será:

  • 0 no processo filho
  • O PID da criança no processo pai
  • -1 no pai, se houve uma falha (não há filho, naturalmente)

Seu código de teste funciona corretamente; ele armazena o valor de retorno de fork() em child_pid e usa if para verificar se é 0 ou não (embora não verifique se há um erro)

23
Michael Mrozek

Eu pensei que fork () cria o mesmo processo, então, inicialmente, que nesse programa, a chamada fork () seria chamada recursivamente para sempre. Eu acho que o novo processo criado a partir de fork () inicia após a chamada fork ()?

Sim. Vamos numerar as linhas:

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 */
}

O fluxo de execução é:

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

... o que explica exatamente a saída que você recebeu.

Se você quiser saber como o programa original e bifurcado pode se comportar de maneira diferente, uma vez que necessariamente compartilham o mesmo código, consulte resposta de Michael Mrozek.

13
badp

A verdadeira solução para isso é

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--