O programa em execução é um processo . A partir deste processo, outro processo pode ser criado. Existe uma relação pai-filho entre os dois processos. Isso pode ser obtido usando uma função de biblioteca chamada fork(). A função fork() divide o processo em execução em dois processos, o existente é conhecido como pai e o novo processo é conhecido como filho. Aqui está um programa que demonstra isso:

// C program to demonstrate
// the above concept
#include <sys/types.h>
#include<stdio.h>
#include <unistd.h> 
  
// Driver code
int main()
{
  printf ("Before Forking\n");
  fork();
  printf ("After Forking\n");
}
Saída
Antes da bifurcação
Após a bifurcação
Antes da bifurcação
Após a bifurcação

Explicação: Todas as instruções após fork() são executadas duas vezes: 

  1. Uma vez pelo processo pai.
  2. Na segunda vez, as instruções são executadas pelo processo filho .

Vamos discutir os seguintes conceitos com mais detalhes:

  1. Processo.
  2. Processo pai.
  3. Processo filho.

Processo : Um processo é um programa em execução, ou seja, um programa ativo. Um processo é mais do que o código do programa, ele inclui o seguinte:

  1. Contador de programa.
  2. Pilha de processos.
  3. Registros.
  4. Código do programa, etc.

Pelo contrário, o código do programa é apenas uma seção de texto.

Um processo muda de estado à medida que é executado. O novo estado depende parcialmente da atividade atual de um processo. Os diferentes estados do processo durante sua execução são:

  1. Novo
  2. Preparar
  3. Correndo
  4. Bloqueado
  5. Terminado.

Um bloco de controle de processo e uma tabela de processo são associados a cada um dos processos. Ele contém as seguintes informações importantes sobre o processo:

  1. Estado do processo.
  2. Número do processo.
  3. Contador de programa.
  4. Lista de arquivos e registros.
  5. Informações da CPU.
  6. Informações de memória, etc.

Processo pai : Todos os processos são criados quando um processo executa a chamada de sistema fork(), exceto o processo de inicialização. O processo que executa a chamada de sistema fork() é o processo pai. Um processo pai é aquele que cria um processo filho usando uma chamada de sistema fork(). Um processo pai pode ter vários processos filho, mas um processo filho apenas um processo pai.

No sucesso de uma chamada de sistema fork():

  • O ID do processo (PID) do processo filho é retornado ao processo pai.
  • 0 é retornado ao processo filho.

Na falha de uma chamada de sistema fork(), 

  • -1 é retornado ao processo pai.
  • Um processo filho não é criado.

Processo filho : um processo filho é criado por um processo pai em um sistema operacional usando uma chamada de sistema fork(). Um processo filho também pode ser conhecido como subprocesso ou subtarefa.

  • Um processo filho é criado como uma cópia de seu processo pai.
  • O processo filho herda a maioria de seus atributos.
  • Se um processo filho não tiver nenhum processo pai, o processo filho será criado diretamente pelo kernel.
  • Se um processo filho sair ou for interrompido, um sinal SIGCHLD será enviado ao processo pai para informar sobre o término ou saída do processo filho.

Por que precisamos criar um processo filho ?
Às vezes, é necessário que um programa execute mais de uma função simultaneamente. Uma vez que esses trabalhos podem estar inter-relacionados, dois programas diferentes para realizá-los não podem ser criados. Por exemplo: Suponha que haja dois trabalhos: copiar o conteúdo do arquivo de origem para o arquivo de destino e exibir uma barra de progresso animada indicando que a cópia do arquivo está em andamento. O arquivo da barra de progresso GIF deve continuar a ser reproduzido até que a cópia do arquivo seja realizada. Assim que o processo de cópia for concluído, a reprodução do arquivo da barra de progresso GIF deve ser interrompida. Como os dois trabalhos estão inter-relacionados, eles não podem ser executados em dois programas diferentes. Além disso, eles não podem ser executados um após o outro. Ambos os trabalhos devem ser executados simultaneamente. 

Nessas ocasiões, fork() é usado para criar um processo filho e, em seguida, escrever o programa de forma que a cópia do arquivo seja feita pelo pai e a exibição do arquivo GIF animado seja feita pelo processo filho .

Programa 1: A tarefa aqui é mostrar como realizar duas tarefas diferentes, mas inter-relacionadas, simultaneamente. Portanto, o código real para copiar e reproduzir o arquivo GIF animado foi ignorado, apenas a abordagem para executar 2 tarefas simultaneamente é mostrada. 

// C program for the above approach
#include <sys/types.h>
  
// Driver Code
int main( )
{
  int pid;
  pid = fork();
  if (pid == 0)
  {
    printf ("In child process\n");
      
    /* code to play animated GIF file */
  }
  else
  {
    printf ("In parent process\n");
      
    /* code to copy file */
  }
}

Explicação: fork() cria um processo filho e duplica o código do processo paino processo filho. A partir daí, a execução da função fork() continua em ambos os processos. Assim, o código de duplicação dentro de fork() é executado uma vez, enquanto o código restante dentro dele é executado tanto no processo pai quanto no filho. Conseqüentemente, o controle voltaria de fork() duas vezes, embora na verdade seja chamado apenas uma vez. Quando o controle retorna do fork() do processo pai, ele retorna o PID do processo filho, enquanto quando o controle retorna do fork() do processo filho, ele sempre retorna um 0. Isso pode ser explorado pelo programa para separar o código que queremos executar no processo pai a partir do código que queremos executar no processo filho. Essa lógica é implementada no programa acima usando uma instrução if. O 'se block' é executado no caso doprocesso filho eo 'bloco else' é executado no caso do processo pai.

Programa 2:
este programa usaria a chamada fork() para criar um processo filho. No processo filho, imprimiríamos o PID do filho e de seu pai, enquanto no processo pai imprimiríamos o PID do pai e de seu filho. 

// C program to implement
// the above approach
# include <sys/types.h>
  
// Driver code
int main()
{
  int pid;
  pid = fork();
  
  if (pid == 0)
  {
    printf ("Child : I am the child process\n");
    printf ("Child : Child’s PID: %d\n", getpid());
    printf ("Child : Parent’s PID: %d\n", getppid());
  }
  else
  {
    printf ("Parent : I am the parent process\n");
    printf ("Parent : Parent’s PID: %d\n", getpid());
    printf ("Parent : Child’s PID: %d\n", pid);
  }
}

Saída:

Child : I am the child process
Child : Child's PID: 4706
Child : Parent's PID: 4705
Parent : I am the Parent process
Parent : Parent's PID: 4705
Parent : Child's PID: 4706