paulo1205
(usa Ubuntu)
Enviado em 24/10/2017 - 18:43h
A utilidade mais patente é permitir que aplicações que fazem I/O em descritores específicos possam usar canais de I/O que normalmente não estão disponíveis nesses descritores.
Quem já usou redirecionamentos no shell usou uma das versões de
dup().
Por exemplo, o comando
ls sempre gera a saída bem sucedida no descritor de arquivos número 1, que é a saída de dados padrão. Quando você digita o comando “
ls > /tmp/x” numa sessão do shell, ele faz três redirecionamentos de arquivo: uma para salvar o descritor original da saída padrão num segundo descritor, outra para redirecionar a saída padrão para um descritor específico (obtido ao abrir o arquivo
/tmp/x, no nosso exemplo), e a terceira, após encerrar a execução do
ls, para restaurar o descritor padrão original, que havia sido salvo num descritor temporário.
O seguinte extrato do comando “
strace sh -c 'ls > /tmp/x'” mostra isso.
open("/tmp/x", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 # abre /tmp/x e recebe descritor 3
fcntl(1, F_DUPFD, 10) = 10 # Salva descritor 1 no descritor 10 (usa fcntl() em vez de dup2(), mas o efeito é semelhante)
close(1) = 0 # Fecha o descritor original
fcntl(10, F_SETFD, FD_CLOEXEC) = 0
dup2(3, 1) = 1 # Sobrescrever descritor 1 com o descritor 3 (saída padrão agora estará em /tmp/x)
close(3) = 0 # Fecha descitor 3 (já o temos aberto no descritor 1
stat("/bin/ls", {st_mode=S_IFREG|0755, st_size=126584, ...}) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fc413e5b9d0) = 23570 # Cria novo processo para executar o ls
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 23570 # espera o ls terminar
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=23570, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn({mask=[]}) = 23570
dup2(10, 1) = 1 # Restaura a saída padrão original para o descritor 1.
close(10) = 0 # Fecha a cópia da saída padrão original
Redirecionamentos de pipes funcionam de maneira semelhante.
Há outras aplicações, também, como obter meios de acesso independentes ao mesmo arquivo ou canal de comunicação. Eu uso essa funcionalidade numa classe que fiz para envelopar acesso a descritores com RAII, de modo que objetos que eventualmente sejam copiados a partir de outros preexistentes usem
dup() em lugar de apenas copiar o descritor, de modo que quando um deles for fechado, os outros objetos que referenciam o mesmo arquivo não sejam afetados.