Conteúdos da cadeira

Processos

Ciclo de vida do processo e as chamadas fork, exec, wait e exit num exemplo pai-filho.

Markdown

Perguntar sobre esta página

ChatGPTClaudePerplexityGeminiCopiar e abrir

Envia o link e pede à IA para ler a página. No Gemini, cola a pergunta copiada.

Ver pergunta para copiar
Nesta página

Um processo nasce, corre, pode criar filhos e morre. O sistema operativo gere esse ciclo de vida com quatro chamadas de sistema que formam o vocabulário central da cadeira: fork para criar, exec para trocar de programa, exit para terminar e wait para recolher. Esta página mostra as quatro a trabalhar juntas.

O ciclo de vida

Um processo está sempre num estado: pronto (quer correr e espera pelo processador), a correr (tem o processador agora), bloqueado (espera por algo, como leitura do disco ou um filho terminar) ou terminado (acabou e espera que o pai recolha o seu estado). O núcleo move os processos entre estes estados à medida que os eventos acontecem. Quando escreves ls na shell, ela cria um processo filho, o filho troca-se pelo programa ls, e a shell bloqueia à espera que ele termine.

Criar com fork

O fork cria um processo filho como cópia do pai: mesmo código, mesmos dados, mesmos descritores abertos. A única diferença inicial é o valor devolvido: o pai recebe o PID do filho e o filho recebe 0. É assim que o programa distingue quem é quem depois da bifurcação:

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void) {
    pid_t pid = fork();
    if (pid == 0) {
        printf("Sou o filho, o meu pai e %d\n", getppid());
    } else {
        printf("Sou o pai, criei o filho %d\n", pid);
    }
    return 0;
}

Corre várias vezes e repara que a ordem das duas linhas varia: pai e filho correm em concorrência e o escalonador decide quem imprime primeiro. Essa variação não é um defeito do exemplo, é a realidade dos processos.

Trocar de programa com exec

Um filho que é uma cópia do pai serve para pouco até se trocar por outro programa com exec. A família exec substitui o código do processo atual pelo programa indicado, mantendo o PID e os descritores. O padrão é sempre o mesmo: fork cria, exec troca, e o terceiro argumento NULL fecha a lista:

#include <unistd.h>

int main(void) {
    pid_t pid = fork();
    if (pid == 0) {
        execlp("ls", "ls", "-l", NULL);
    }
    return 0;
}

Se o execlp funcionar, o filho deixa de correr o teu código e passa a correr ls. Se falhar (programa inexistente, por exemplo), o filho continua no teu código a seguir à chamada, por isso trata sempre esse caso.

Terminar e recolher: exit e wait

Um processo termina com exit (ou retornando do main) e deixa um estado de saída, o número que a shell guarda em $?. Mas terminar não chega: o pai tem de recolher esse estado com wait, que bloqueia o pai até um filho terminar e devolve o seu PID. Um filho terminado à espera de recolha chama-se zombie: já não corre nem ocupa memória de trabalho, mas ocupa a sua entrada na tabela de processos. Zombies acumulados são lixo do pai distraído, não do sistema.

Junta as quatro peças. O pai cria o filho, o filho troca-se por outro programa, o pai espera e lê o estado:

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void) {
    pid_t pid = fork();
    if (pid == 0) {
        execlp("ls", "ls", NULL);
    } else {
        int estado;
        wait(&estado);
        printf("O filho terminou\n");
    }
    return 0;
}

Sem o wait, o pai podia terminar primeiro e o filho ficava órfão, adotado pelo processo de arranque. Com o wait, a ordem é garantida: a mensagem do pai sai sempre depois da listagem.

Para levar para a próxima página

Criar, trocar, terminar e recolher chegam para gerir um processo de cada vez. Mas há dezenas de processos prontos e um processador: quem corre a seguir decide-se no escalonamento.

Ver o ficheiro no GitHub

À tua maneira

Escolhe como preferes ler.

Aparência
Ajustar cores e largura
Cor de destaque do tema FEUP
Tipo de letra

Álgebra, lógica e uma ideia de cada vez.

As tuas escolhas ficam guardadas neste navegador.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.