exemplos práticos usam dup ou dup2
-
19-09-2019 - |
Pergunta
Eu sei o que dup
/ dup2
faz, mas eu tenho nenhuma idéia de quando seria usado.
Qualquer exemplos práticos?
Graças.
Solução
Um exemplo de uso seria I / redirecionamento O. Para isso, você desembolsar um processo filho e fechar o stdin ou stdout descritores de arquivos (0 e 1) e, em seguida, você faz um dup () em outro FileDescriptor de sua escolha que irá agora ser mapeado para o menor descritor de arquivo disponível, que é neste caso 0 ou 1.
Usando isso, você pode agora exec qualquer processo filho que é, possivelmente, desconhecem o seu pedido e sempre que a criança escreve no stdout (ou lê de stdin, o que você configurou) os dados são escritos no FileDescriptor fornecido vez.
Escudos usar isso para implementar comandos com tubos, por exemplo, /bin/ls | more
ligando a saída padrão de um processo para a entrada padrão da outra.
Outras dicas
O melhor cenário para entender dup e dup2 é redirecionamento.
A primeira coisa que precisamos saber é que o sistema tem 3 ids de arquivo padrão (ou variáveis ??que indicam fontes de saída ou de entrada) que lida com a entrada e saída. Eles são stdin
, stdout
, stderr
, em números inteiros são 0
, 1
, 2
. A maioria das funções como fprintf
ou cout
são diretamente saída para stdout
.
Se queremos redirecionar a saída, uma maneira é dar, por exemplo, função fprintf
mais argumentos indicando in
e out
.
No entanto, há uma maneira mais elegante: podemos substituir os ids de arquivo padrão para torná-los apontando para o arquivo que deseja receber a saída. dup
e dup2
exatamente trabalho nesta situação.
Vamos começar com um exemplo simples agora: suponha que deseja redirecionar a saída do fprintf
para um arquivo txt chamado "chinaisbetter.txt". Primeiro de tudo o que precisamos para abrir este arquivo
int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);
Em seguida, queremos stdout
para apontar para "chinaisbetter.txt" usando a função dup:
dup2(fw,1);
Agora stdout (1) aponta para o descritor de "chinaisbetter.txt", embora ainda é 1, mas a saída é redirecionada agora.
Então você pode usar printf
como normal, mas os resultados serão no arquivo txt em vez de mostrar diretamente na tela:
printf("Are you kidding me? \n");
PS :
-
Isso só dá uma explicação intuitiva, você pode precisar verificar a página de manual ou informações detalhadas. Na verdade, podemos dizer "copiar" aqui, eles não são a cópia de tudo.
-
O ID de arquivo aqui está se referindo ao manipulador do arquivo. O descritor de arquivo mencionado acima é uma estrutura de informação do arquivo de registros.
Quando você está curioso sobre funções POSIX, especialmente aqueles que parecem duplicar-se, é geralmente bom para verificar o padrão em si . Na parte inferior normalmente você vai ver exemplos, bem como o raciocínio por trás da implementação (e existência) de ambos.
Neste caso:
As seções a seguir são informativos.
Exemplos
saída Redirecionando padrão para um arquivo
O exemplo a seguir fecha a saída padrão para os processos atuais, reatribuirá saída padrão para ir para o arquivo referenciado por pfd
, e fecha o descritor de arquivo original para limpar.
#include <unistd.h>
...
int pfd;
...
close(1);
dup(pfd);
close(pfd);
...
Mensagens de erro Redirecionando
O exemplo a seguir redirecionamentos mensagens stderr
para stdout
.
#include <unistd.h>
...
dup2(2, 1); // 2-stderr; 1-stdout
...
Application Usage
Nenhum.
Justificação
As funções dup()
e dup2()
são redundantes. Seus serviços também são fornecidos pela função fcntl()
. Eles foram incluídos neste volume de IEEE Std 1.003,1-2.001 principalmente por razões históricas, uma vez que muitas aplicações existentes usá-los.
Enquanto o segmento de código mostrado é muito breve um comportamento semelhante ao dup2()
, uma implementação conforme com base em outras funções definidas neste volume de IEEE Std 1.003,1-2001 é significativamente mais complexo. Menos óbvio é o possível efeito de uma função de captura de sinal que poderia ser invocada entre as etapas e alocar ou descritores de arquivos desalocar. Isso poderia ser evitado através do bloqueio de sinais.
A função dup2()
não está marcada obsoleto porque apresenta uma versão segura de tipo de funcionalidade fornecida em uma versão tipo inseguro por fcntl()
. Ele é usado no POSIX Ada vinculativo.
A função dup2()
não se destina a utilização em regiões críticas como um mecanismo de sincronização.
Na descrição do [EBADF], o caso de fildes estar fora de alcance é coberto pelo caso dado de fildes não ser válido. As descrições para fildes
e fildes2
são diferentes porque o único tipo de invalidez que é relevante para fildes2
é se ele está fora de alcance; isto é, não importa se fildes2
refere-se a um arquivo aberto quando a chamada dup2()
é feita.
Future Directions
Nenhum.
Veja também
close()
, fcntl()
, open()
, o volume Definições Base do IEEE Std 1.003,1-2.001, <unistd.h>
Histórico de alterações
Primeiro lançado em Issue 1. Derivado do Issue 1 do SVID.
Um exemplo prático está redirecionando mensagens de saída para algum outro fluxo como um arquivo de log. Aqui está um código de exemplo para I / O redirecionamento.
Por favor, consulte post original aqui
#include <stdio.h>
main()
{
int fd;
fpos_t pos;
printf("stdout, ");
fflush(stdout);
fgetpos(stdout, &pos);
fd = dup(fileno(stdout));
freopen("stdout.out", "w", stdout);
f();
fflush(stdout);
dup2(fd, fileno(stdout));
close(fd);
clearerr(stdout);
fsetpos(stdout, &pos); /* for C9X */
printf("stdout again\n");
}
f()
{
printf("stdout in f()");
}
I / O redirecionamento no shell provavelmente ser implementada usando chamadas de sistema dup2 / fcnlt.
Podemos facilmente imitar o tipo $program 2>&1 > logfile.log
de redirecionamento utilizando a função dup2.
O programa abaixo redirecionamentos ambos stdout e stderr .i.e emula o comportamento de $program 2>&1 > output
usando o dup2.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int
main(void){
int close_this_fd;
dup2(close_this_fd = open("output", O_WRONLY), 1);
dup2(1,2);
close(close_this_fd);
fprintf(stdout, "standard output\n");
fprintf(stderr, "standard error\n");
fflush(stdout);
sleep(100); //sleep to examine the filedes in /proc/pid/fd level.
return;
}
vagrant@precise64:/vagrant/advC$ ./a.out
^Z
[2]+ Stopped ./a.out
vagrant@precise64:/vagrant/advC$ cat output
standard error
standard output
vagrant@precise64:/vagrant/advC$ ll /proc/2761/fd
total 0
dr-x------ 2 vagrant vagrant 0 Jun 20 22:07 ./
dr-xr-xr-x 8 vagrant vagrant 0 Jun 20 22:07 ../
lrwx------ 1 vagrant vagrant 64 Jun 20 22:07 0 -> /dev/pts/0
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 1 -> /vagrant/advC/output
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 2 -> /vagrant/advC/output