Durante a aula de projeto de sistemas operacionais do curso de Ciência da Computação da Universidade Luterana do Brasil, campus Gravataí, em 12 de março de 2009, eu estava explicando aos alunos o funcionamento da chamada de sistema
fork() do Unix, quando ocorreu um fato inusitado. Esta chamada cria uma cópia do processo atual, duplicando código e valores de variáveis. Trata-se da chamada básica do Unix para criar um novo processo. Como código e variáveis são duplicados, as diferenças entre o processo criador (também chamado de pai) e o processo criado (chamado de filho) são:
- o novo processo terá um PID (Process IDentification) diferente do processo criador;
- e a chamada fork() retornará o PID do processo-filho para o processo-pai e 0 para o processo-filho.
E, para ambos os processos, a execução continuará na instrução seguinte à chamada fork().
No restante deste artigo são apresentados alguns exemplos de uso da chamada fork() para testar o seu funcionamento, o "desafio" que gerou a "situação inusitada", a explicação para a origem da situação inusitada e a prova da explicação. Por fim, são apresentadas algumas conclusões.
Desafios iniciais
Depois de descrever o funcionamento da chamada fork(), sempre proponho alguns desafios aos alunos para ver se eles entenderam a explicação. O primeiro desafio gosto de apresentar lembrando aos alunos que nas disciplinas de linguagens de programação eles sempre aprendem que, no caso de comandos como if e else, se a condição do if for verdadeira, o comando ou bloco executado será o do if. Caso a condição seja falsa, o comando ou bloco executado será o do else. Pergunto-lhes então o que seria impresso depois do trecho de código-fonte mostrado na Figura 1.
p = fork();
if (p == 0)
printf("FILHO\n");
else
printf("PAI\n");
Figura 1 - Exemplo de código-fonte com if
A resposta, por mais estranha que seja, não pode ser outra que não: as duas cadeias de caracteres são impressas. A execução do fork() duplica o processo, de forma que, apesar de termos um único código-fonte, teremos 2 processos executando o if. Para um dos processos a condição do if será falsa, para o outro, não.
Outro desafio interessante é questionar quanto ao número de caracteres 'x' impresso após a execução do trecho de código-fonte da Figura 2.
fork();
fork();
fork();
printf("x");
Figura 2 - Exemplo de código-fonte com vários fork() em sequência
Às vezes é possível ouvir alguns números improváveis antes da resposta correta: oito. Após o primeiro fork(), teremos 2 processos. Cada um deles executa um fork(), resultando em 4 processos. E, por fim, cada um destes 4 processos executa um último fork(), resultando em 8 processos. E cada um destes 8 processos imprime um caractere 'x'.