Dado o programa fork.c a seguir:
fork.c
/*
Criação de processos em UNIX.
Compilar com gcc -Wall fork.c -o fork
Carlos Maziero, DINF/UFPR 2020
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main ()
{
int retval ;
printf (Ola, sou o processo %5d\n, getpid()) ;
retval = fork () ;
printf ([retval: %5d] sou %5d, filho de %5d\n, retval, getpid(), getppid()) ;
if ( retval < 0 ) // erro no fork()
{
perror (Erro) ;
exit (1) ;
}
else
if ( retval > 0 ) // sou o processo pai
wait (0) ;
else // sou o processo filho
sleep (5) ;
printf (Tchau de %5d!\n, getpid()) ;
exit (0) ;
}
- Analise seu código e o comente detalhadamente.
fork.c
/*
Criação de processos em UNIX.
Compilar com gcc -Wall fork.c -o fork
Carlos Maziero, DINF/UFPR 2020
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main ()
{
int retval ;
printf (Ola, sou o processo %5d\n, getpid()) ;
retval = fork () ;
printf ([retval: %5d] sou %5d, filho de %5d\n, retval, getpid(), getppid()) ;
if ( retval < 0 ) // erro no fork()
{
perror (Erro) ;
exit (1) ;
}
else
if ( retval > 0 ) // sou o processo pai
wait (0) ;
else // sou o processo filho
sleep (5) ;
printf (Tchau de %5d!\n, getpid()) ;
exit (0) ;
}
Passo 1
Então, a gente tem aqui um exercício que pede para analisar e comentar detalhadamente um código em C chamado
fork.c. O foco principal desse código é a criação de processos no sistema operacional UNIX usando a função fork(). Para entender e resolver esse exercício, a gente vai precisar conhecer alguns conceitos básicos de sistemas operacionais, como processos, e entender como a função fork() funciona para criar processos filhos a partir de um processo pai. Também vamos precisar entender algumas funções básicas de C, como printf(), getpid(), getppid(), perror(), exit(), wait() e sleep().Passo 2
Vamos começar analisando o início do código:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
Aqui, o programa inclui várias bibliotecas padrão em C:
<unistd.h>: contém as declarações para as funções POSIX, comofork(),getpid(), etc.<stdio.h>: usada para funções de entrada e saída, comoprintf().<stdlib.h>: inclui funções de utilidade geral, comoexit().<sys/types.h>e<sys/wait.h>: usadas para manipular tipos de dados e funções relacionadas à espera de processos, comowait().
Passo 3
Agora, vamos para a função
main():int main ()
{
int retval ;
printf (Ola, sou o processo %5d\n, getpid()) ;
retval = fork () ;
printf ([retval: %5d] sou %5d, filho de %5d\n, retval, getpid(), getppid()) ;
...
}
Primeiro, é declarado um inteiro
retval que vai armazenar o valor de retorno da função fork().Em seguida, temos uma chamada para
printf():printf (Ola, sou o processo %5d\n, getpid()) ;
Parece que há um pequeno erro na sintaxe do
printf(). O correto seria:printf("Ola, sou o processo %5d\n", getpid());
Aqui,
printf() está imprimindo uma mensagem que inclui o ID do processo atual, obtido pela função getpid().Passo 4
Agora, a linha importante:
retval = fork () ;
A função
fork() é usada para criar um novo processo. Quando fork() é chamado, ele cria um processo filho que é uma cópia quase exata do processo pai. O valor de retorno de fork() é:- Negativo: se a criação do processo filho falhar.
- Zero: para o processo filho recém-criado.
- Positivo: o ID do processo filho para o processo pai.
Esse valor de retorno é armazenado na variável
retval.Passo 5
Após o
fork(), temos outro printf():printf ([retval: %5d] sou %5d, filho de %5d\n, retval, getpid(), getppid()) ;
Novamente, há um pequeno erro de sintaxe. O correto seria:
printf("[retval: %5d] sou %5d, filho de %5d\n", retval, getpid(), getppid());
Aqui, o programa está imprimindo três informações:
retval: o valor retornado porfork().getpid(): o ID do processo atual.getppid(): o ID do processo pai.
Isso ajuda a identificar se estamos no processo pai ou no filho e qual é a relação entre eles.
Passo 6
Em seguida, temos uma estrutura condicional para tratar diferentes casos com base no valor de
retval:if ( retval < 0 ) // erro no fork()
{
perror (Erro) ;
exit (1) ;
}
else
if ( retval > 0 ) // sou o processo pai
wait (0) ;
else // sou o processo filho
sleep (5) ;
Vamos detalhar isso:
-
retval < 0: Significa que houve um erro ao tentar criar o processo filho.perror("Erro");: A funçãoperror()imprime uma mensagem de erro baseada no erro que ocorreu.exit(1);: Encerra o programa com o código de saída 1, indicando que houve um erro.
-
retval > 0: Isso ocorre no processo pai, poisretvalrecebe o ID do processo filho.wait(0);: A funçãowait()faz com que o processo pai espere até que o processo filho termine sua execução.
-
else: Esse é o caso em queretval == 0, ou seja, estamos no processo filho.sleep(5);: Faz com que o processo filho “durma” por 5 segundos antes de continuar.
Passo 7
Depois da estrutura condicional, temos mais um
printf() e a finalização do programa:printf (Tchau de %5d!\n, getpid()) ;
exit (0) ;
Novamente, corrigindo a sintaxe:
printf("Tchau de %5d!\n", getpid());
exit(0);
Aqui, o programa está imprimindo uma mensagem de despedida que inclui o ID do processo atual e, em seguida, encerra o processo com
exit(0);, indicando uma finalização bem-sucedida.Passo 8
Resumindo, o que esse programa faz é:
- Imprime o ID do processo inicial.
- Tenta criar um processo filho usando
fork(). - Imprime o valor retornado por
fork(), o ID do processo atual e o ID do processo pai. - Se
fork()falhar, imprime uma mensagem de erro e encerra. - Se for o processo pai, espera que o processo filho termine.
- Se for o processo filho, “dorme” por 5 segundos.
- Ambos os processos (pai e filho) imprimem uma mensagem de despedida e encerram.
Resposta
O código
fork.c demonstra como criar um processo filho a partir de um processo pai usando a função fork() em sistemas UNIX. Ele imprime informações sobre os processos, trata possíveis erros na criação do processo filho e coordena a execução entre pai e filho usando funções como wait() e sleep(). Essa análise detalhada ajuda a entender como os processos se relacionam e como o gerenciamento de processos funciona em ambiente UNIX.