Pergunta

Eu sei o que dup / dup2 faz, mas eu tenho nenhuma idéia de quando seria usado.

Qualquer exemplos práticos?

Graças.

Foi útil?

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 :

  1. 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.

  2. 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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top