dup, dup2, dup3 - Dupliquer un descripteur de fichier
Bibliothèque C standard (
libc,
-lc)
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <fcntl.h> /* Définition des constantes O_* */
#include <unistd.h>
int dup3(int oldfd, int newfd, int flags);
L'appel système
dup() affecte un nouveau descripteur de fichier
qui se rapporte à la même description de fichier ouvert que le
descripteur
oldfd (pour une explication sur les descriptions de fichier
ouvert, voir
open(2)). Le numéro du nouveau descripteur de
fichier est garanti d'être le plus petit qui n'est pas utilisé
par le processus appelant.
Après un appel réussi, l'ancien et le nouveau descripteur peuvent
être utilisés de manière interchangeable. Ils
référencent la même description de fichier et ainsi
partagent les pointeurs de position et les drapeaux. Par exemple, si le
pointeur de position est modifié en utilisant
lseek(2) sur l'un
des descripteurs, la position est également changée pour
l'autre.
Les deux descripteurs de fichier ne partagent pas les attributs (celui
close‐on‐exec. L'attribut close‐on‐exec (
FD_CLOEXEC ; consultez
fcntl(2)) pour le descripteur en
double est désactivé.
L'appel système
dup2() effectue la même tâche que
dup(), mais au lieu de prendre le plus petit numéro de
descripteur de fichier inutilisé, il utilise le numéro de
descripteur passé dans
newfd. En d'autres termes, le descripteur
de fichier
newfd est modifié pour se rapporter à la
même description de fichier ouvert que
oldfd.
Si le descripteur de fichier
newfd était ouvert, il est
fermé avant d'être réutilisé ; la fermeture
se passe en silence (c'est-à-dire que les messages d'erreur à la
fermeture ne sont pas indiqués par
dup2()).
Les étapes de fermeture et de réutilisation du descripteur de
fichier
newfd sont effectuées de manière
atomique.
Cela est important, parce qu'essayer d'implémenter des
fonctionnalités équivalentes avec
close(2) et
dup() entraînerait une situation de compétition
(« race condition »), où
newfd
pourrait être réutilisé entre les deux étapes. Une
telle réutilisation peut intervenir si le programme principal est
interrompu par un gestionnaire de signaux qui alloue un descripteur de
fichier, ou parce qu'un processus léger qui s'exécute en
parallèle alloue un descripteur de fichier.
Notez les points suivants :
- •
- Si oldfd n'est pas un descripteur de fichier
valable, alors l'appel échoue et newfd n'est pas
fermé.
- •
- Si oldfd est un descripteur de fichier valable et
newfd a la même valeur que oldfd, alors dup2()
ne fait rien et renvoie newfd.
dup3() est identique à
dup2(), à l'exception
de :
- •
- L'appelant peut forcer l'attribut close-on-exec à
être positionné pour le nouveau descripteur de fichier en
ajoutant O_CLOEXEC dans flags. Consultez la description de
cet attribut dans open(2) pour savoir pourquoi cela peut
être utile.
- •
- Si oldfd est égal à newfd,
alors dup3() échoue avec l'erreur EINVAL.
Ces appels système renvoient le nouveau descripteur en cas de
succès, ou
-1 en cas d'échec, auquel cas
errno est
positionné pour indiquer l'erreur.
- EBADF
-
oldfd n'est pas un descripteur de fichier
ouvert.
- EBADF
-
newfd est en dehors de la plage autorisée
pour des descripteurs de fichier (voir le point sur RLIMIT_NOFILE
dans getrlimit(2)).
- EBUSY
- (Linux seulement) Cette valeur peut être
renvoyée par dup2() ou dup3() lors d'une concurrence
critique avec open(2) et dup().
- EINTR
- L'appel dup2() ou dup3() a été
interrompu par un signal ; consultez signal(7).
- EINVAL
- (dup3()) flags contient une valeur
incorrecte.
- EINVAL
- (dup3()) flags était égal
à newfd.
- EMFILE
- La limite du nombre de descripteurs de fichier ouverts par
processus a été atteinte (voir le point sur
RLIMIT_NOFILE dans getrlimit(2)).
dup3() a été ajouté dans
Linux 2.6.27 ; sa prise en charge dans la glibc est disponible
à partir de la glibc 2.9.
dup(),
dup2() : POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.
dup3() est spécifique à Linux.
Les erreurs renvoyées par
dup2() sont différentes de celles
retournées par
fcntl(...,
F_DUPFD, ...
) si
newfd n'est pas dans les valeurs autorisées. Sur certains
systèmes,
dup2 retourne aussi parfois
EINVAL comme
F_DUPFD.
Si
newfd était ouvert, toute erreur qui aurait été
rapportée au moment de
close(2) est perdue. Si cela est
d'importance, alors, à moins que le programme ne soit monothread et
n'alloue pas de descripteurs de fichier dans des gestionnaires de signaux,
l'approche correcte est de
ne pas fermer
newfd avant d'appeler
dup2(), à cause de la condition de concurrence décrite
ci-dessus. À la place, un code semblable à celui ci-dessous peut
être utilisé :
/* Obtenir une copie de 'newfd' qui peut ensuite être
utilisée pour vérifier les erreurs de close() ; une
erreur EBADF signifie que 'newfd' n'était pas ouvert. */
tmpfd = dup(newfd);
if (tmpfd == -1 && errno != EBADF) {
/* Gérer une erreur inattendue de dup(). */
}
/* Copier 'oldfd' dans 'newfd' de manière atomique */
if (dup2(oldfd, newfd) == -1) {
/* Gérer une erreur de dup2(). */0
}
/* Maintenant, vérifier les erreurs de close() sur le fichier
originellement désigné par 'newfd'. */
if (tmpfd != -1) {
if (close(tmpfd) == -1) {
/* Gérer les erreurs de close(). */
}
}
close(2),
fcntl(2),
open(2),
pidfd_getfd(2)
La traduction française de cette page de manuel a été
créée par Christophe Blaess
<
https://www.blaess.fr/christophe/>, Stéphan Rafin
<
[email protected]>, Thierry Vignaud
<
[email protected]>, François Micaux, Alain Portal
<
[email protected]>, Jean-Philippe Guérard
<
[email protected]>, Jean-Luc Coulon (f5ibh)
<
[email protected]>, Julien Cristau
<
[email protected]>, Thomas Huriaux <
[email protected]>,
Nicolas François <
[email protected]>, Florentin
Duneau <
[email protected]>, Simon Paillard
<
[email protected]>, Denis Barbier
<
[email protected]>, David Prévot <
[email protected]> et
Jean-Philippe MENGUAL <
[email protected]>
Cette traduction est une documentation libre ; veuillez vous reporter
à la
GNU
General Public License version 3 concernant les conditions de copie
et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel,
veuillez envoyer un message à
[email protected]