A chamada do sistema fork é usada para criar um novo processo, que é chamado de processo filho , que é executado simultaneamente com o processo que faz a chamada fork() (processo pai). Depois que um novo processo filho é criado, ambos os processos executarão a próxima instrução após a chamada de sistema fork(). Um processo filho usa o mesmo pc (contador de programa), os mesmos registros de CPU, os mesmos arquivos abertos que usam no processo pai.

Não leva parâmetros e retorna um valor inteiro. Abaixo estão os diferentes valores retornados por fork().

Valor negativo : a criação de um processo filho não foi bem-sucedida.
Zero : Retornado ao processo filho recém-criado.
Valor positivo : devolvido ao pai ou ao autor da chamada. O valor contém o ID do processo do processo filho recém-criado.

criando um processo de bifurcação

Observe que os programas acima não compilam no ambiente Windows.

  1. Prever a saída do seguinte programa: .




    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    int main()
    {
      
        // make two process which run same
        // program after this instruction
        fork();
      
        printf("Hello world!\n");
        return 0;
    }

    Saída:

    Olá Mundo!
    Olá Mundo!
    


  2. Calcule o número de vezes que hello é impresso:




    #include <stdio.h>
    #include <sys/types.h>
    int main()
    {
        fork();
        fork();
        fork();
        printf("hello\n");
        return 0;
    }

    Saída:

    Olá
    Olá
    Olá
    Olá
    Olá
    Olá
    Olá
    Olá
    

    O número de vezes que 'hello' é impresso é igual ao número de processos criados. Número total de processos = 2 n , onde n é o número de chamadas de sistema de bifurcação. Então aqui n = 3, 2 3 = 8

    Vamos colocar alguns nomes de rótulos para as três linhas:

    garfo(); // Linha 1
    garfo(); // Linha 2
    garfo(); // Linha 3
    
           L1 // Haverá 1 processo filho 
        / \ // criado pela linha 1.
      L2 L2 // Haverá 2 processos filho
     / \ / \ // criado pela linha 2
    L3 L3 L3 L3 // Haverá 4 processos filho 
                    // criado pela linha 3
    
    

    Portanto, há um total de oito processos (novos processos filho e um processo original).

    Se quisermos representar a relação entre os processos como uma hierarquia em árvore, seria o seguinte:

    O processo principal:
    Processos P0 criados pela 1ª bifurcação: P1
    Processos criados pela 2ª bifurcação: P2, P3
    Processos criados pela 3ª bifurcação: P4, P5, P6, P7

                 P0
             / | \
           P1 P4 P2
          / \ \
        P3 P6 P5
       /
     P7
    
  3. Preveja o resultado do seguinte programa:




    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    void forkexample()
    {
        // child process because return value zero
        if (fork() == 0)
            printf("Hello from Child!\n");
      
        // parent process because return value non-zero.
        else
            printf("Hello from Parent!\n");
    }
    int main()
    {
        forkexample();
        return 0;
    }

    Saída:



    1
    Hello from Child!
    Olá do pai!
         (ou)
    2
    Olá do pai!
    Hello from Child!
    

    No código acima, um processo filho é criado. fork() retorna 0 no processo filho e um inteiro positivo no processo pai.
    Aqui, duas saídas são possíveis porque o processo pai e o processo filho estão sendo executados simultaneamente. Portanto, não sabemos se o sistema operacional primeiro dará controle ao processo pai ou ao processo filho.

    Importante: o processo pai e o processo filho estão executando o mesmo programa, mas isso não significa que sejam idênticos. O SO aloca dados e estados diferentes para esses dois processos, e o fluxo de controle desses processos pode ser diferente. Veja o próximo exemplo:

  4. Preveja o resultado do seguinte programa:




    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
      
    void forkexample()
    {
        int x = 1;
      
        if (fork() == 0)
            printf("Child has x = %d\n", ++x);
        else
            printf("Parent has x = %d\n", --x);
    }
    int main()
    {
        forkexample();
        return 0;
    }

    Saída:

    Pai tem x = 0
    Criança tem x = 2
         (ou)
    Criança tem x = 2
    Pai tem x = 0
    

    Aqui, a mudança da variável global em um processo não afeta dois outros processos porque os dados / estado de dois processos são diferentes. E também pai e filho são executados simultaneamente, de modo que duas saídas são possíveis.

fork() vs exec()

A chamada de sistema fork cria um novo processo. O novo processo criado por fork() é uma cópia do processo atual, exceto pelo valor retornado. A chamada de sistema exec() substitui o processo atual por um novo programa.

Exercício:

  1. Um processo executa o seguinte código:




    for (i = 0; i < n; i++)
        fork();

    O número total de processos filho criados é: (GATE-CS-2008)
    (A) n
    (B) 2 ^ n - 1
    (C) 2 ^ n
    (D) 2 ^ (n + 1) - 1;

    Veja esta solução.

  2. Considere o seguinte fragmento de código:




    if (fork() == 0) {
        a = a + 5;
        printf("%d, %d\n", a, &a);
    }
    else {
        a = a –5;
        printf("%d, %d\n", a, &a);
    }

    Sejam u, v os valores impressos pelo processo pai e x, y os valores impressos pelo processo filho. Qual das opções a seguir é VERDADEIRA? (GATE-CS-2005)
    (A) u = x + 10 ev = y
    (B) u = x + 10 ev! = Y
    (C) u + 10 = x e v = y
    (D) u + 10 = x e v! = y
    Veja isto para a solução.

  3. Preveja a saída do programa abaixo.




    #include <stdio.h>
    #include <unistd.h>
    int main()
    {
        fork();
        fork() && fork() || fork();
        fork();
      
        printf("forked\n");
        return 0;
    }

    Veja isso para solução

Artigos relacionados:
Programa C para demonstrar processos fork() e pipe()
Zombie e Orphan em C
fork() e processos p / w de memória compartilhada criados com ele.

Referências:
http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html

Este artigo é uma contribuição de Team GeeksforGeeks e Kadam Patel . Se você gosta de GeeksforGeeks e gostaria de contribuir, você também pode escrever um artigo usando contribute.geeksforgeeks.org ou enviar o seu artigo para contribute@geeksforgeeks.org. Veja o seu artigo na página principal do GeeksforGeeks e ajude outros Geeks.

Escreva comentários se encontrar algo incorreto ou se quiser compartilhar mais informações sobre o tópico discutido acima.

Quer aprender com os melhores vídeos com curadoria e problemas práticos, confira o C Foundation Course for Basic to Advanced C.