next up previous
Next: Primitiva system() Up: As Primitivas exec() Previous: As Primitivas exec()

Comportamento em relação aos descritores abertos

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.


next up previous
Next: Primitiva system() Up: As Primitivas exec() Previous: As Primitivas exec()
Celso Alberto Saibel Santos 2000-11-14