J'essaie de comprendre l'utilisation de dup2
et dup
.
Depuis la page de manuel:
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).
Pourquoi aurais-je besoin de cet appel système? à quoi sert de dupliquer le descripteur de fichier?
Si j'ai le descripteur de fichier, pourquoi voudrais-je en faire une copie?
J'apprécierais si vous pouviez m'expliquer et me donner un exemple où dup2
/ dup
est nécessaire.
Merci
dup
oudup2
? Vous devez appelerpipe(2)
et ensuite avoir l'un des descripteurs de fichierdup
STDIN_FILENO
Réponses:
L'appel système dup duplique un descripteur de fichier existant, en renvoyant un nouveau qui fait référence au même objet d'E / S sous-jacent.
Dup permet aux shells d'implémenter des commandes comme celle-ci:
ls existing-file non-existing-file > tmp1 2>&1
Le 2> & 1 indique au shell de donner à la commande un descripteur de fichier 2 qui est un double du descripteur 1. (ie stderr & stdout pointent vers le même fd).
Maintenant, le message d'erreur pour appeler ls sur un fichier non existant et la sortie correcte de ls sur le fichier existant apparaissent dans le fichier tmp1 .
L'exemple de code suivant exécute le programme wc avec une entrée standard connectée à l'extrémité de lecture d'un tube.
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]); }
L'enfant copie la fin de lecture sur le descripteur de fichier 0, ferme le fichier de scriptors dans p et exécute wc. Lorsque wc lit depuis son entrée standard, il lit depuis le tube.
C'est ainsi que les tubes sont implémentés en utilisant dup, eh bien qu'une utilisation de dup maintenant vous utilisez pipe pour construire autre chose, c'est la beauté des appels système, vous construisez une chose après l'autre en utilisant des outils qui sont déjà là, ces outils ont été à leur tour construits en utilisant autre chose et ainsi de suite .. A la fin les appels système sont les outils les plus basiques que vous obtenez dans le noyau
À votre santé :)
la source
dup
Est-ce donc utile pour l'appelant et non pour lels
programme lui-même? Y a-t-il un avantage à avoirdup
utilisé dans un programme comme ls lui-même s'il a déjà accès au fichier? Ici, par exemple,ls
écrit des erreurs dans2
lesquelles est codé en dur, j'ai donc un moyen de le contourner en tant que consommateur dels
. Je pense que c'est un point subtil non?dup(p[STDIN])
mais jetez ensuite le résultat. Vouliez-vous utiliserdup2(p[STDIN], 0)
?dup
renvoie le "descripteur numéroté le plus petit actuellement non utilisé par le processus." Puisque fd 0 vient juste d'être fermé,dup
devrait renvoyer 0.dup2
est explicite sur quel fd devrait être utilisé, au lieu d'utiliser simplement le fd libre le plus bas, donc je préférerais cela.exec*
partir d'un processus multithread. Mais je ne suis pas un expert en threading :)Une autre raison de dupliquer un descripteur de fichier est de l'utiliser avec
fdopen
.fclose
ferme le descripteur de fichier qui a été transmisfdopen
, donc si vous ne voulez pas que le descripteur de fichier d'origine soit fermé, vous devez d'abord le dupliquerdup
.la source
fdopen()
semble ne pas dupliquer un descripteur de fichier, il crée simplement un tampon dans l'espace utilisateur.dup
le fd avant de le passerfdopen
carfclose
le fermera.FILE
handle pour accéder à un fichier ouvert préexistant via les interfaces stdio, vous devez appelerfclose
pour désallouer ceFILE
handle. Si vous voulez continuer à utiliser le fichier ouvert sous-jacent, ou si votre architecture logicielle est telle que le code «propriétaire» original du descripteur de fichier le feraclose
, le fait que celafclose
ferme également le descripteur de fichier sous-jacent que vous avez remisfdopen
est un problème. Vous pouvez éviter ce problème en utilisantdup
pour créer un nouveau descripteur de fichier pour le même fichier ouvert à transmettrefdopen
, afin quefclose
ne ferme pas l'original.FILE
, plutôt que de le copier . C'est quelque chose dont les utilisateurs doivent être conscients. Les consommateurs qui doivent conserver unefd
poignée utilisable en plus de l'FILE
objet doivent dupliquer le fichierfd
. C'est tout.FILE
fois que vous en avez transféré la propriété.dup permet de rediriger la sortie d'un processus.
Par exemple, si vous souhaitez enregistrer la sortie d'un processus, vous dupliquez la sortie (fd = 1), vous redirigez le fd dupliqué vers un fichier, puis forkez et exécutez le processus, et lorsque le processus se termine, vous redirigez le fichier sauvé fd en sortie.
la source
Certains points liés à dup / dup2 peuvent être notés s'il vous plaît
dup / dup2 - Techniquement, le but est de partager une entrée de table de fichiers dans un même processus par différentes poignées. (Si nous forçons, le descripteur est dupliqué par défaut dans le processus enfant et l'entrée de la table de fichiers est également partagée).
Cela signifie que nous pouvons avoir plus d'un descripteur de fichier ayant éventuellement des attributs différents pour une seule entrée de table de fichier ouverte en utilisant la fonction dup / dup2.
(Bien qu'il semble actuellement que seul l'indicateur FD_CLOEXEC soit le seul attribut d'un descripteur de fichier).
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);
Les différences sont (pour le dernier) - Mis à part une certaine valeur errno entre dup2 et fcntl close suivie de fcntl peut soulever des conditions de concurrence puisque deux appels de fonction sont impliqués.
Les détails peuvent être vérifiés sur http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
Un exemple d'utilisation -
Un exemple intéressant lors de l'implémentation du contrôle de travail dans un shell, où l'utilisation de dup / dup2 peut être vue ..dans le lien ci-dessous
http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs
la source