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.