web-dev-qa-db-fra.com

Quelqu'un peut-il expliquer ce que dup () en C fait?

Je sais que dup, dup2, dup3 " crée une copie du descripteur de fichier oldfd " (à partir des pages de manuel). Cependant je ne peux pas le digérer.

Comme je le sais, les descripteurs de fichier ne sont que nombres pour garder une trace des emplacements des fichiers et de leur direction (entrée/sortie). Ne serait-il pas plus facile de simplement

fd=fd2;

Chaque fois que nous voulons dupliquer un descripteur de fichier?

Et quelque chose d'autre..

dup () utilise le descripteur inutilisé avec le plus petit numéro pour le nouveau descripteur.

Cela signifie-t-il qu'il peut également prendre pour valeur stdin , stdout ou stderr si nous supposons que nous avons close () - ed l'un de ces?

18
Pithikos

Je voulais juste me répondre à la deuxième question après avoir essayé un peu.

La réponse estOUI. Un descripteur de fichier que vous créez peut prendre les valeurs 0, 1, 2 si stdin, stdout ou stderr sont fermés.

Exemple:

close(1);     //closing stdout
newfd=dup(1); //newfd takes value of least available fd number

Où cela arrive aux descripteurs de fichiers:

0 stdin     .--------------.     0 stdin     .--------------.     0 stdin
1 stdout   =|   close(1)   :=>   2 stderr   =| newfd=dup(1) :=>   1 newfd
2 stderr    '--------------'                 '--------------'     2 stderr
14
Pithikos

Un descripteur de fichier est un peu plus qu'un nombre. Il porte également divers états semi-cachés (qu'il soit ouvert ou non, à quelle description de fichier il fait référence, ainsi que certains drapeaux). dup duplique ces informations, vous pouvez par exemple fermez les deux descripteurs indépendamment. fd=fd2 ne le fait pas.

11
n.m.

La chose la plus importante à propos de dup () est qu’elle renvoie le plus petit entier disponible pour un nouveau descripteur de fichier. C'est la base de la redirection:

int fd_redirect_to = open("file", O_CREAT);
close(1); /* stdout */
int fd_to_redirect = dup(fd_redirect_to); /* magically returns 1: stdout */
close(fd_redirect_to); /* we don't need this */

Après cela, quoi que ce soit écrit dans le descripteur de fichier 1 (stdout), passe par magie dans "fichier".

6
SzG

Supposons que vous écriviez un programme Shell et que vous souhaitiez rediriger stdin et stdout dans un programme que vous souhaitez exécuter. Cela pourrait ressembler à quelque chose comme ça:

fdin = open(infile, O_RDONLY);
fdout = open(outfile, O_WRONLY);
// Check for errors, send messages to stdout.
...
int pid = fork(0);
if(pid == 0) {
    close(0);
    dup(fdin);
    close(fdin);
    close(1);
    dup(fdout);
    close(fdout);
    execvp(program, argv);
}
// Parent process cleans up, maybe waits for child.
...

dup2 () est un moyen un peu plus pratique de le faire. close () dup () peut être remplacé par:

dup2(fdin, 0);
dup2(fdout, 1);

La raison pour laquelle vous souhaitez procéder est que vous souhaitez signaler les erreurs à stdout (ou stderr) afin que vous ne puissiez pas les fermer et ouvrir un nouveau fichier dans le processus enfant. Deuxièmement, ce serait une perte de temps si l'un des appels à open () renvoyait une erreur.

5
Richard Pennington

voir cette page , stdout peut être alias dup(1)...

2
Karel Frajták

appel système de dup () et dup2 ()

• L'appel système dup () duplique un descripteur de fichier ouvert et renvoie le nouveau descripteur de fichier.

• Le nouveau descripteur de fichier a les propriétés suivantes en commun avec le descripteur de fichier d'origine: 1. fait référence au même fichier ou canal ouvert. 2. a le même pointeur de fichier - c'est-à-dire que les deux descripteurs de fichier partagent un pointeur de fichier. 3. a le même mode d'accès, qu'il soit en lecture, en écriture ou en lecture et écriture.

• Dup () est sûr de renvoyer un descripteur de fichier avec la valeur entière la plus basse disponible. C'est en raison de cette fonction de retour du descripteur de fichier non utilisé disponible que les processus effectuent la redirection des E/S.

int dup (descripteur de fichier)

int dup2 (file_descriptor1, file_descriptor2)

0
Mahendra suthar

Juste un conseil sur " dupliquer la sortie standard ".

Sur certains systèmes Unix (mais pas GNU/Linux)

fd = open("/dev/fd/1", O_WRONLY);

c'est équivalent à:

fd = dup(1);
0
b3h3m0th

Exemple:

close(1);     //closing stdout
newfd=dup(1); //newfd takes value of least available fd number

Où cela arrive aux descripteurs de fichiers:

0 stdin     .--------------.     0 stdin     .--------------.     0 stdin
1 stdout   =|   close(1)   :=>   2 stderr   =| newfd=dup(1) :=>   1 newfd
2 stderr    '--------------'                 '--------------'     2 stderr

Une question se pose à nouveau: comment puis-je dup() un descripteur de fichier que j'ai déjà fermé?

Je doute que vous ayez conduit l'expérience ci-dessus avec le résultat indiqué, car cela ne serait pas conforme à la norme - cf. dup :

Le dupLa fonction () échouera si:

[EBADF]
Le fildes L'argument n'est pas un descripteur de fichier ouvert valide.

Ainsi, après la séquence de code affichée, newfd ne doit pas être 1, mais plutôt -1 et errnoEBADF.

0
Armali