Estou tentando entender o uso de dup2
e dup
.
Na página de manual:
DESCRIPTION
dup and dup2 create a copy of the file descriptor oldfd.
After successful return of dup or dup2, the old and new descriptors may
be used interchangeably. They share locks, file position pointers and
flags; for example, if the file position is modified by using lseek on
one of the descriptors, the position is also changed for the other.
The two descriptors do not share the close-on-exec flag, however.
dup uses the lowest-numbered unused descriptor for the new descriptor.
dup2 makes newfd be the copy of oldfd, closing newfd first if necessary.
RETURN VALUE
dup and dup2 return the new descriptor, or -1 if an error occurred
(in which case, errno is set appropriately).
Por que eu precisaria dessa chamada de sistema? qual é a utilidade de duplicar o descritor de arquivo?
Se eu tiver o descritor de arquivo, por que desejaria fazer uma cópia dele?
Eu apreciaria se você pudesse me explicar e me dar um exemplo onde dup2
/ dup
é necessário.
obrigado
dup
oudup2
? Você precisa ligarpipe(2)
e, em seguida, ter um dos descritores de arquivodup
-ed para, por exemploSTDIN_FILENO
Respostas:
A chamada de sistema dup duplica um descritor de arquivo existente, retornando um novo que se refere ao mesmo objeto de E / S subjacente.
O Dup permite que os shells implementem comandos como este:
ls existing-file non-existing-file > tmp1 2>&1
O 2> & 1 diz ao shell para fornecer ao comando um descritor de arquivo 2 que é uma duplicata do descritor 1. (isto é, stderr & stdout apontam para o mesmo fd).
Agora a mensagem de erro para chamar ls em um arquivo não existente e a saída correta de ls em um arquivo existente aparecem no arquivo tmp1 .
O código de exemplo a seguir executa o programa wc com a entrada padrão conectada à extremidade de leitura de um tubo.
int p[2]; char *argv[2]; argv[0] = "wc"; argv[1] = 0; pipe(p); if(fork() == 0) { close(STDIN); //CHILD CLOSING stdin dup(p[STDIN]); // copies the fd of read end of pipe into its fd i.e 0 (STDIN) close(p[STDIN]); close(p[STDOUT]); exec("/bin/wc", argv); } else { write(p[STDOUT], "hello world\n", 12); close(p[STDIN]); close(p[STDOUT]); }
O filho copia a extremidade de leitura para o descritor de arquivo 0, fecha o arquivo de scriptors em p e execs wc. Quando o wc lê a partir de sua entrada padrão, ele lê a partir do tubo.
É assim que os pipes são implementados usando dup, bem, esse uso de dup agora você usa o pipe para construir outra coisa, essa é a beleza das chamadas do sistema, você constrói uma coisa após a outra usando ferramentas que já estão lá, essas ferramentas foram construídas internamente usando algo mais e assim por diante .. No final, as chamadas de sistema são as ferramentas mais básicas que você obtém no kernel
Felicidades :)
fonte
dup
é útil para o chamador e não para ols
programa em si? Existe algum benefício em terdup
usado um programa como o próprio ls se já tiver acesso ao arquivo? Aqui, por exemplo,ls
grava erros2
que são codificados, então tenho uma maneira de substituí-lo como consumidor dels
. Acho que é um ponto sutil, não?dup(p[STDIN])
mas depois jogando fora o resultado. Você quis dizer usardup2(p[STDIN], 0)
?dup
retorna o "descritor de menor número atualmente não em uso pelo processo." Como fd 0 acabou de ser fechado,dup
deve retornar 0.dup2
é explícito sobre qual fd deve ser usado, em vez de apenas usar o fd livre mais baixo, então eu preferiria isso.exec*
de um processo multithread. Mas eu não sou um especialista em threading :)Outra razão para duplicar um descritor de arquivo é usá-lo com
fdopen
.fclose
fecha o descritor de arquivo que foi passadofdopen
, portanto, se você não quiser que o descritor de arquivo original seja fechado, é necessário duplicá-lodup
primeiro.fonte
fdopen()
parece não duplicar um descritor de arquivo, ele apenas cria um buffer no espaço do usuário.dup
fd antes de passá-lo para,fdopen
poisfclose
irá fechá-lo.FILE
identificador para acessar um arquivo aberto preexistente por meio de interfaces stdio, será necessário chamarfclose
para desalocar esseFILE
identificador. Se você quiser continuar usando o arquivo aberto subjacente, ou se sua arquitetura de software for tal que o código do "proprietário" original para o descritor de arquivo o faráclose
, o fato defclose
também fechar o descritor de arquivo subjacente que você entregoufdopen
é um problema. Você pode evitar esse problema usandodup
para fazer um novo descritor de arquivo para o mesmo arquivo aberto passarfdopen
, de modo quefclose
não feche o original.FILE
, ao invés de copiá- lo. Isso é algo que os usuários devem estar cientes. Os consumidores que precisam reter umfd
identificador utilizável além doFILE
objeto devem duplicar ofd
. Isso é tudo.FILE
depois que você transfere a propriedade para ele.dup é usado para redirecionar a saída de um processo.
Por exemplo, se você deseja salvar a saída de um processo, duplica a saída (fd = 1), redireciona o fd duplicado para um arquivo, bifurca e executa o processo e, quando o processo termina, redireciona novamente o salvou o fd na saída.
fonte
Alguns pontos relacionados a dup / dup2 podem ser observados, por favor
dup / dup2 - Tecnicamente, o objetivo é compartilhar uma entrada de tabela de arquivo dentro de um único processo por meio de diferentes identificadores. (Se estivermos bifurcando, o descritor é duplicado por padrão no processo filho e a entrada da tabela de arquivos também é compartilhada).
Isso significa que podemos ter mais de um descritor de arquivo com atributos possivelmente diferentes para uma única entrada de tabela de arquivo aberta usando a função dup / dup2.
(Embora atualmente pareça apenas o sinalizador FD_CLOEXEC é o único atributo para um descritor de arquivo).
http://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html
dup(fd) is equivalent to fcntl(fd, F_DUPFD, 0); dup2(fildes, fildes2); is equivalent to close(fildes2); fcntl(fildes, F_DUPFD, fildes2);
As diferenças são (para o último) - Exceto por algum valor errno entre dup2 e fcntl close seguido por fcntl pode aumentar as condições de corrida, pois duas chamadas de função estão envolvidas.
Os detalhes podem ser verificados em http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
Um exemplo de uso -
Um exemplo interessante durante a implementação de controle de trabalho em um shell, onde o uso de dup / dup2 pode ser visto .. no link abaixo
http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs
fonte