A princípio, os descritores de arquivos abertos antes da chamada exec() continuama abertos, exceto se for determinado o contrário (via primitiva fcntl(). Um dos efeitos do recobrimento dos segmentos dos processo numa chamada exec é a destruição do buffer associado ao arquivo na região usuário, e portanto a perda de informações contidas por ele. Para contornar o problema, deve-se forçar o esvaziamento completo do buffer antes da chamada exec de forma a não perder seus dados, utilizando-se para isso a função flush().
Exemplo 1:
/* arquivo test_buffer1.c */ #include <stdio.h> #include <unistd.h> int main() { printf("Voce nao vai conseguir ler este texto") ; execl("/bin/ls","ls","test_buffer1.c",NULL) ; exit(0); }
Resultado da execução:
euler:~/> test_buffer1 test_buffer1.c
A mensagem não é impressa, pois o buffer de saída não foi esvaziado antes de ser destruído pela chamada exec.
Exemplo 2:
/* arquivo test_buffer2.c */ #include <stdio.h> #include <unistd.h> int main() { printf("Voce nao vai conseguir ler este texto\n") ; execl("/bin/ls","ls","test_buffer1.c",NULL) ; exit(0); }
Resultado da execução:
euler:~/> test_buffer2 Voce nao vai conseguir ler este texto test_buffer1.c
A mensagem agora é impressa, pois o caracter \n esvazia o buffer de saída e retorna à linha.
Exemplo 3:
/* arquivo test_buffer3.c */ #include <stdio.h> #include <unistd.h> int main() { printf("Voce nao vai conseguir ler este texto\n") ; fflush(stdout) ; execl("/bin/ls","ls","test_buffer1.c",NULL) ; exit(0); }
Resultado da execução:
euler:~/> test_buffer3 Voce nao vai conseguir ler este texto test_buffer1.c
O resultado é semelhante ao anterior, só que desta vez, o
buffer é esvaziado através da primitiva fflush.
Observações: stdout corresponde à saída padrão em UNIX, que é neste caso a tela. Note também que comandos internos do shell não podem ser executados através de exec(). Por exemplo, não teria nenhum efeito a utilização de um processo filho associado a exec() para a execução do comando shell cd. Isto porque o atributo mudado no processo filho (no caso o diretório corrente) não pode ser remontado ao pai uma vez que o filho morrerá imediatamente após a execução do exec. Verifique a afirmação através do exemplo a seguir:
Exemplo:
/* arquivo test_cd.c */ /* a mudanca de diretorio so e valida */ /* durante o tempo de execucao do processo */ #include <stdio.h> #include <unistd.h> int main() { if(chdir("..")==-1) /* retorno ao diretorio predecente */ { perror("impossivel de achar o diretorio especificado") ; exit(-1); } /* sera executado um pwd que vai matar o processo */ /* e que vai retornar o diretorio corrente onde ele esta */ if(execl("/bin/pwd","pwd",NULL)==-1) { perror("impossivel de executar o pwd") ; exit(-1) ; } exit(0); }
Faça um pwd no diretorio corrente. Lance o programa test_cd e verifique então que o diretório foi momentaneamente alterado durante a execução deste. Espere o fim do programa e execute novamente um pwd. O diretório corrente não foi alterado como era de se esperar.