Talvez estimulado pelo fado da resposta correta ao desafio da Figura 2 não ter demorado a aparecer, pensei então em outro desafio. E se o fork() for colocado em um laço? Antes de lançar o desafio para a turma, ainda considerei se a explicação não poderia se tornar mais complicada do que eu gostaria. Mas quem trabalha com Sistemas Operacionais não pode ter medo de códigos ou explicações complicadas. E a situação poderia ilustrar perfeitamente as consequências de se colocar um fork() dentro de um laço sem maiores cuidados.
Lancei então o desafio para a turma e não demorou muito para que o fato inusitado, ao qual me referi no início do artigo, surgisse. O desafio consistia em determinar quantos caracteres 'x' apareceriam na tela depois da execução do código-fonte da Figura 3.
#include <stdio.h>
#include <unistd.h>
int main()
{
int i;
for (i=0; i<2; ++i) {
fork();
printf("x");
}
return(0);
}
Figura 3 - Exemplo de código-fonte para o novo desafio
Resultados diferentes
Recomendei que a turma digitasse e testasse o código da Figura 3 e em seguida discutiríamos os resultados. Para minha surpresa a maioria da turma obteve 8 como resposta e dois alunos obtiveram 6...
Analisamos então o código-fonte e chegamos à seguinte conclusão: na primeira iteração do laço, um fork() seria executado e dois processos imprimiriam o caractere 'x', indo em seguida para a segunda iteração. Nesta segunda iteração (ainda bem que não usei 10 como limite para o laço...), os dois processos executariam uma chamada fork(), tendo-se 4 processos, cada um imprimindo mais um caractere 'x'. Total de caracteres 'x' impressos: 6 (seis).
Verificamos então as diferenças entre os códigos que resultaram no valor esperado (seis) e no valor que a maioria obteve (oito). A maioria digitou o código exatamente da forma apresentada na Figura 3. Os dois alunos que obtiveram o valor esperado, digitaram o código "à sua maneira", fazendo pequenas adaptações. Considerando as poucas variações que um código tão pequeno pode apresentar, chega a ser difícil compreender a origem da diferença de resultado.
Isolando e eliminando as diferenças insignificantes, ficou claro que o que estava ocasionando a diferença era um '\n' (caractere de nova linha) colocado na cadeia de caracteres da chamada printf(). Uma chamada fflush(stdout) colocada logo após o printf() tinha o mesmo efeito do uso de printf() com '\n'. A chamada fflush(stdout) esvazia o buffer de saída do processo (que por padrão é o terminal de vídeo), garantindo que tudo o que foi mandado imprimir seja visualizado imediatamente. O código com esta chamada, que gera o resultado esperado (seis), pode ser visto na Figura 4.
#include <stdio.h>
#include <unistd.h>
int main()
{
int i;
for (i=0; i<2; ++i) {
fork();
printf("x");
fflush(stdout);
}
return(0);
}
Figura 4 - Exemplo de código-fonte para o novo desafio com fflush(stdout)
A questão principal era então: por que o primeiro código apresentou dois caracteres "x" a mais além do esperado? De onde saíram estes dois caracteres "x"?
Como o horário da aula estava se encerrando, não foi possível encontrar uma resposta para a questão na hora.