Dado o programa fork-execve.c a seguir:
fork-execve.c
/*
Criação de processos em UNIX, com execução de outro binário
Compilar com gcc -Wall fork-execve.c -o fork-execve
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 argc, char *argv[], char *envp[])
{
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
{
execve (/bin/date, argv, envp) ;
perror (Erro) ;
}
printf (Tchau de %5d!\n, getpid()) ;
exit (0) ;
}
  1. Analise seu código e o comente detalhadamente.

Passo 1

Resumo do enunciado: a gente tem um programa em C chamado fork-execve.c que mostra como criar processos no UNIX com fork(), trocar a imagem do processo filho com execve() e aguardar o filho com wait(). O conteúdo da matéria é “Controle de processos em UNIX” e a gente vai precisar entender as chamadas de sistema:
  • fork(): cria um processo filho
  • execve(): substitui o processo atual por outro executável
  • wait(): faz o pai esperar o término do filho
  • getpid(), getppid(): obtêm IDs de processos

Passo 2

Analisando os includes e a assinatura de main:
#include <unistd.h>    // protótipos de fork, execve, getpid, getppid
#include <stdio.h>     // protótipos de printf, perror
#include <stdlib.h>    // protótipos de exit
#include <sys/types.h> // tipos de dados (pid_t, etc.)
#include <sys/wait.h>  // protótipo de wait

int main(int argc, char *argv[], char *envp[])
Comentário:
  • <unistd.h> traz as funções de baixo nível do UNIX.
  • <stdio.h> e <stdlib.h> são padrões de C.
  • <sys/types.h> e <sys/wait.h> são necessários para wait().
  • argc, argv[] e envp[] são, respectivamente, o número de argumentos, o vetor de argumentos e o vetor de variáveis de ambiente.

Passo 3

Primeiros prints e a chamada de fork():
int retval;
printf("Ola, sou o processo %5d\n", getpid());
retval = fork();
printf("[retval: %5d] sou %5d, filho de %5d\n",
       retval, getpid(), getppid());
Comentário:
  1. getpid() retorna o PID (Process ID) do processo atual. O primeiro printf mostra esse PID.
  2. fork() cria um clone do processo. Ela devolve:
    • < 0 se deu erro
    • == 0 no processo filho
    • > 0 no processo pai (o valor é o PID do filho)
  3. Depois do fork() os dois processos (pai e filho) continuam a execução a partir da próxima linha. O segundo printf mostra retval (que indica se é pai ou filho), o PID atual e o PID do pai (getppid()).

Passo 4

Tratando erro no fork():
if (retval < 0) {
    // erro no fork()
    perror("Erro: ");
    exit(1);
}
Comentário:
  • Se retval < 0, ocorreu um problema ao criar o filho.
  • perror imprime no stderr uma mensagem explicando o erro com base em errno.
  • exit(1) finaliza o programa informando que houve falha.

Passo 5

Divisão de comportamento de pai e filho:
else if (retval > 0) {
    // sou o processo pai
    wait(0);
} else {
    // sou o processo filho
    execve("/bin/date", argv, envp);
    perror("Erro");
}
Comentário:
  • retval > 0: estamos no processo pai. Chamamos wait(0), que bloqueia o pai até o filho terminar.
  • retval == 0: estamos no processo filho.
    • execve("/bin/date", argv, envp) substitui a imagem do filho pelo binário /bin/date, passando os mesmos argv e envp. Se der tudo certo, a partir daí o código do filho é o de date.
    • Se execve falhar, ela retorna e a gente cai em perror("Erro") para reportar o problema.

Passo 6

Print final e saída:
printf("Tchau de %5d!\n", getpid());
exit(0);
Comentário:
  • Essa parte é executada tanto pelo pai (depois que o filho termina, por causa do wait) quanto pelo filho, caso o execve falhe (porque um execve bem‐sucedido não retorna).
  • getpid() mostra quem está dizendo “Tchau”.
  • exit(0) termina o processo com código de sucesso.

Resposta

O código acima está comentado linha a linha, explicando cada chamada de sistema e fluxo de execução entre pai e filho, conforme solicitado.

Exercícios relacionados