web-dev-qa-db-fra.com

des exemples pratiques utilisent dup ou dup2

Je sais ce que dup/dup2 fait, mais je ne sais pas quand cela sera utilisé.

Des exemples pratiques?

Merci.

60
pierrotlefou

Un exemple d'utilisation serait la redirection d'E/S. Pour cela, vous branchez un processus enfant et fermez les descripteurs de fichier stdin ou stdout (0 et 1), puis effectuez un dup () sur un autre archiveur de fichiers de votre choix qui sera désormais mappé sur le descripteur de fichier disponible le plus bas, qui se trouve dans ce fichier. cas 0 ou 1.

En utilisant cela, vous pouvez maintenant exécuter tout processus enfant qui ignore peut-être votre application et chaque fois que l'enfant écrit sur la sortie standard (ou lit à partir de stdin, peu importe ce que vous avez configuré), les données sont écrites sur le gestionnaire de fichiers fourni.

Les shells l'utilisent pour implémenter des commandes avec des tubes, par exemple. /bin/ls | more en connectant le stdout d'un processus au stdin de l'autre.

59
Alfonso

Le meilleur scénario pour comprendre dup et dup2 est la redirection.
La première chose à savoir est que le système a 3 identificateurs de fichier par défaut (ou variables indiquant les sorties ou les sources d’entrée) qui traitent des entrées et des sorties. Ils sont stdin, stdout, stderr, dans les entiers, ils sont 0, 1, 2. La plupart des fonctions telles que fprintf ou cout sont directement générées dans stdout
Si nous voulons rediriger la sortie, une solution consiste, par exemple, à donner à la fonction fprintf plus d'arguments indiquant in et out
Cependant, il existe un moyen plus élégant: nous pouvons écraser les identifiants de fichier par défaut pour les faire pointer vers le fichier que nous souhaitons recevoir. dup et dup2 fonctionnent exactement dans cette situation.
Commençons par un exemple simple: supposons que nous voulions rediriger la sortie de fprintf vers un fichier txt nommé "chinaisbetter.txt". Tout d'abord nous devons ouvrir ce fichier 

int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);

Ensuite, nous voulons que stdout pointe sur "chinaisbetter.txt" en utilisant la fonction dup:

dup2(fw,1);

Stdout (1) pointe maintenant sur le descripteur de "chinaisbetter.txt" même s'il en reste 1, mais la sortie est maintenant redirigée.
Ensuite, vous pouvez utiliser printf comme d'habitude, mais les résultats seront dans le fichier txt au lieu de s'afficher directement à l'écran:

printf("Are you kidding me? \n");

PS:

  1. Cela donne simplement une explication intuitive, vous devrez peut-être consulter la page de manuel ou des informations détaillées. En fait, on dit "copier" ici, ils ne copient pas tout.

  2. L'identifiant de fichier fait ici référence au gestionnaire du fichier. Le descripteur de fichier mentionné ci-dessus est une structure des informations du fichier d'enregistrements.

20
ZijunLost

Lorsque vous êtes curieux de connaître les fonctions POSIX, en particulier celles qui semblent se dupliquer, il est généralement bon de vérifier la norme elle-même En bas, vous verrez généralement des exemples, ainsi qu'un raisonnement derrière la mise en œuvre (et l'existence) des deux.

Dans ce cas:

Les sections suivantes sont à titre d'information.

Exemples

Redirection de la sortie standard dans un fichier

L'exemple suivant ferme la sortie standard pour les processus en cours, réaffecte la sortie standard pour accéder au fichier référencé par pfd et ferme le descripteur de fichier d'origine à nettoyer.

#include <unistd.h>
...
int pfd;
...
close(1);
dup(pfd);
close(pfd);
...

Redirection des messages d'erreur

L'exemple suivant redirige les messages de stderr à stdout.

#include <unistd.h>
...
dup2(2, 1); // 2-stderr; 1-stdout
...

Utilisation de l'application

Aucun.

Raisonnement

Les fonctions dup() et dup2() sont redondantes. Leurs services sont également fournis par la fonction fcntl(). Ils ont été inclus dans le présent volume de la norme IEEE Standard 1003.1-2001 principalement pour des raisons historiques, car de nombreuses applications existantes les utilisent.

Le comportement du segment de code bref présenté est très similaire à celui de dup2(), mais une implémentation conforme basée sur les autres fonctions définies dans ce volume de la norme IEEE Standard 1003.1-2001 est considérablement plus complexe. La moins évidente est l’effet possible d’une fonction de capture de signal pouvant être invoquée entre les étapes et allouer ou désallouer des descripteurs de fichier. Cela pourrait être évité en bloquant les signaux.

La fonction dup2() n'est pas marquée comme étant obsolète, car elle présente une version de sécurité de type fournie dans une version de type unsafe par fcntl(). Il est utilisé dans la liaison POSIX Ada.

La fonction dup2() n'est pas conçue pour être utilisée dans les régions critiques en tant que mécanisme de synchronisation.

Dans la description de [EBADF], le cas de fildes hors limites est couvert par le cas donné de fildes non valide. Les descriptions de fildes et fildes2 sont différentes, car le seul type d'invalidité pertinent pour fildes2 consiste à déterminer si elle est hors limites. Autrement dit, peu importe que fildes2 fasse référence à un fichier ouvert lorsque l'appel dup2() est effectué.

Directions futures

Aucun.

Voir également

close(), fcntl(), open(), le volume Définitions de base de la norme IEEE 1003.1-2001, <unistd.h>

Changer l'historique

Première publication dans le numéro 1. Dérivé du numéro 1 du SVID.

9
Tim Post

Un exemple pratique consiste à rediriger les messages de sortie vers un autre flux, tel qu'un fichier journal. Voici un exemple de code pour la redirection d'E/S.
S'il vous plaît se référer à l'article original ici

#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()");
}
5
vinit dhatrak

La redirection des E/S dans le shell serait très probablement mise en œuvre à l'aide d'appels système dup2/fcnlt.

Nous pouvons facilement émuler le type de redirection $program 2>&1 > logfile.log à l’aide de la fonction dup2. 

Le programme ci-dessous redirige à la fois stdout et stderr .i.e émule le comportement de $program 2>&1 > output à l’aide de 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
0
maitreyak