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, poisretval
recebe 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.