|
|
FCNTL
Section: Manuel du programmeur Linux (2) Updated: 30 juillet 2003 Index
Return to Main Contents
NOM
fcntl - Manipuler un descripteur de fichier.
SYNOPSIS
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
DESCRIPTION
fcntl
permet de se livrer à diverses opérations sur le descripteur de fichier
fd.
L'opération en question est déterminée par la valeur de l'argument
cmd.
Manipulation de Close-on-exec
- F_DUPFD
-
Trouve le plus petit numéro de descripteur libre supérieur
égal à
arg
et le transforme en copie de
fd.
Ceci est différent de
dup(2)
qui utilise exactement le descripteur transmis.
Le nouveau et l'ancien descripteurs deviennent interchangeables. Ils partagent
les verrous, l'indicateur de position et les attributs. Si par exemple la
tête de lecture/écriture est déplacée en utilisant
lseek
sur l'un des deux descripteurs, la position sera aussi modifiée pour l'autre.
Les deux descripteurs ne partagent toutefois pas l'attribut Close-on-exec.
L'attribut Close-on-exec de la copie est désactivé, ce qui signifie qu'il
ne sera pas fermé lors d'un exec().
En cas de réussite, le nouveau descripteur est renvoyé.
- F_GETFD
-
Retourne la valeur de l'attribut Close-on-exec. Si le bit
FD_CLOEXEC
est 0, le fichier restera ouvert même au travers d'un
exec,
autrement il sera fermé.
- F_SETFD
-
Positionne l'attribut Close-on-Exec avec la valeur précisée par le bit
FD_CLOEXEC
de
arg.
Attribut d'état du fichier
Un descripteur de fichier dispose de certains attributs, initialisés par
open(2)
et eventuellement modifiés par
fcnt(2).
Les attributs sont partagés entre les copies (obtenues avec
dup(2),
fork(2),
etc.) du même descripteur de fichier.
Les attributs et leurs sémantiques sont décrits dans la page
open(2).
- F_GETFL
-
Renvoie l'attribut d'état du descripteur.
- F_SETFL
-
Fixe les nouveaux attributs pour le descripteur de fichier à la valeur
indiquée par
arg.
Les bits restants (mode d'accès, attributs de création) de
arg
sont ignorés.
Sous Linux, cette commande ne peut changer que O_APPEND, O_NONBLOCK, O_ASYNC,
et O_DIRECT.
Verrouillages coopératifs
F_GETLK, F_SETLK et F_SETLKW
servent à gérer les verrouillages d'enregistrements (de segments ou de
régions de fichiers).
Le troisième argument
lock
est un pointeur sur une structure qui a au moins les champs suivants
(dans un ordre non spécifié).
struct flock {
...
short l_type; /* Type de verrouillage : F_RDLCK,
F_WRLCK, F_UNLCK */
short l_whence; /* Interprétation de l_start:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Décalage de début du verrouillage */
off_t l_len; /* Nombre d'octets du verrouillage */
pid_t l_pid; /* PID du processus bloquant notre verrou
(F_GETLK seulement) */
...
};
Les champs
l_whence, l_start, et l_len
de cette structure indiquent l'intervalle à verrouiller.
l_start
est le décalage de début du verrouillage et s'interpréte
par rapport :
au début du fichier (si
l_whence
vaut
SEEK_SET);
à la position actuelle dans le fichier (si
l_whence
vaut
SEEK_CUR);
ou la fin du fichier (si
l_whence
vaut
SEEK_END).
Dans les deux derniers cas,
l_start
peut être un nombe négatif, à condition de ne
pas indiquer une position avant le début du fichier.
l_len
est un entier non-négatif (mais voir les NOTES plus bas) indiquant
le nombre d'octets à verrouiller.
On peut verrouiller des octets après la fin du fichier, mais
pas avant son début.
Fournir un 0 dans
l_len
a un sens particulier : verrouiller tous les octets de la position indiquée
par
l_whence et l_start
jusqu'à la fin du fichier, quelque soit sa taille.
Le champ
l_type
peut servir à placer un verrou en lecture
(F_RDLCK)
ou en écriture
(F_WDLCK)
sur u fichier.
Un nombre quelconque de processus peuvent tenir un verrou en lecture (partagé),
sur une région d'un fichier, mais un seul peut avoir un verrou en écriture
(exclusif). Un verrou en écriture exclut tous les autres verrous, aussi bien
en lecture qu'en écriture.
Un processus donné ne peut tenir qu'un seul verrou sur une région d'un fichier,
si un nouveau verrou y est appliqué, alors le verrou précédent est
converti suivant le noàuveau type.
Ceci peut entraîner le découpage, la réduction ou l'extension du verrou
existant si le nombre d'octets du nouveau verrou ne coincide pas exactement
avec celuin de l'ancien.
- F_SETLK
-
Acquérir (si
l_type
vaut
F_RDLCK
ou
F_WRLCK)
ou libérer (si
l_type
vaut
F_UNLCK)
le verrou sur les octets indiqués par les champs
l_whence, l_start, et l_len
de
lock.
Si un conflit avec un verrou tenu par un autre processus existe,
cet appel renvoie -1 et positionne
errno
aux valeurs
EACCES
ou
EAGAIN.
- F_SETLKW
-
Comme
F_SETLK,
mais attend la libération du verrou au lieu de retourner une
erreur.
Si un signal à intercepter est reçu pendant l'attente,
l'appel est interrompu et renverra immédiatement (après retour du
gestionnaire de signaux) la valeur -1.
errno
sera remplie avec la valeur
EINTR.
- F_GETLK
-
En entrée dans cette routine,
lock
décrit un verrou que nous aimerions placer sur le fichier.
Si le verrouillage est possible,
fcntl()
ne le fait pas, mais renvoie
F_UNLCK
dans le champ
l_type
de
lock
et laisse les autres champs de la structure inchangés.
Si un ou plusieurs verrouillages incompatibles empêcheraient l'action,
alors
fcntl()
renvoie des informations sur l'un de ces verrous dans les champs
l_type, l_whence, l_start, et l_len
de
lock
et remplit
l_pid
avec le PID du processus tenant le verrou.
Pour pouvoir placer un verrou en lecture,
fd
doit être ouvert en lecture au moins.
Pour placer un verrou en écriture,
fd
doit être ouver en écriture.
Pour placer les deux types de verrous, il faut une ouverture en lecture-écriture.
Outre la suppression par un
F_UNLCK
explicite, les verrous sont automatiquement libérés lorsque le processus
se termine, ou s'il ferme
l'un
des descripteurs se réfèrant au fichier sur lequel le verrou est placé.
C'est dangereux : cela signifie qu'un processus peut perdre un verrou sur
un fichier comme
/etc/passwd
ou
/etc/mtab
si pour une raison quelconque une fonction de bibliothèque décide de l'uvrir
puis de le refermer.
Les verrouillages d'enregistrements ne sont pas hérités par les enfants lors d'un
fork(2),
mais sont préservés au cours d'un
execve(2).
À cause des buffers gérés par la bibliothèque
stdio(3),
l'utilisation des verrous d'enregistrements avec les routines de celle-ci
est déconseillé. Utilisez
read(2) et write(2)
plutôt.
Verrouillage obligatoire
(NON-POSIX)
Les verrouillages d'enregistrements ci-dessus peuvent être coopératifs ou
impératifs (coopératifs par défaut). Pour utiliser des verrous impératifs,
ce type de verrouillage doit être activé sur le système de fichiers
contenant le fichier à verrouiller
(en utilisant l'option "-o mand" de
mount(8))
et validé pour le fichier lui-même (en désactivant la permission d'exécution
du groupe et en activant le bit de permission
Set-GID).
Les verrouillages coopératifs ne fonctionnent qu'entre processus qui les
utilisent. Les verrouillages impératifs fonctionnent avec
tous les processus.
Gestion des signaux
F_GETOWN, F_SETOWN, F_GETSIG et F_SETSIG
servent à gérer lies signaux de disponibilité d'entrée/sortie :
- F_GETOWN
-
obtient le PID ou l'ID du groupe de processus qui reçoit les signaux
SIGIO et SIGURG pour les événements concernant le descripteur de fichier
fd.
Les groupes de processus sont renvoyés sous forme de valeurs négatives.
- F_SETOWN
-
fixe le PID ou l'ID du groupe de processus qui recevront les signaux
SIGIO et SIGURG pour les événements concernant le descripteur
fd.
Les groupes de processus sont formulés en tant que valeurs négatives.
(F_SETSIG
peut servir à indiquer un autre signal que SIGIO).
Si vous fixez l'attribut
O_ASYNC
sur un descripteur de fichier (soit en utilisant ce drapeau lors de l'appel à
open(2),
soit en utilisant la commande
F_SETFL
de
fcntl),
un signal SIGIO est envoyé dès que l'entrée ou la sortie sont possibles sur
ce descripteur.
Le processus, ou le groupe de processus, susceptibles de
recevoir le signal peut être indiqué avec la commande
F_SETOWN
de la fonction
fcntl.
Si le descripteur est une socket, ceci permet également la réception de
signaux SIGURG lorsque des données hors-bande arrivent sur la socket.
(SIGURG est émis dans toutes les situations où l'appel
select(2)
aurait indiqué que la socket est dans une "situation exceptionnelle").
Si le descripteur de fichier correspond à un terminal, le signal SIGIO est
envoyé au groupe de processus en avant-plan sur ce terminal.
- F_GETSIG
-
Renvoie le numéro du signal émis lorsque l'entrée ou la sortie deviennent possibles.
Une valeur nulle signifie l'émission de SIGIO. Toute autre valeur (y compris
SIGIO) précise le signal émis, et des informations supplémentaires
seront disponibles pour le gestionnaire s'il est installé avec SA_SIGINFO.
- F_SETSIG
-
Indique le signal à émettre lorsque l'entrée ou la sortie deviennent possibles.
Une valeur nulle signifie l'émission de SIGIO. Toute autre valeur (y compris
SIGIO) précise le signal à émettre, et des informations supplémentaires
seront disponibles pour le gestionnaire s'il est installé avec SA_SIGINFO.
En utilisant F_SETDIG avec une valeur non-nulle, et en configurant SA_SIGINFO
pour le gestionnaire (voir
sigaction(2)),
des informations supplémentaires sur les événements d'E/S sont fournies au
gestionnaire à travers une structure
siginfo_t.
Si le champ
si_code
indique que la source est SI_SIGIO, le champ
si_fd
fournit le descripteur du fichier concerné par l'événement. Sinon il n'y
a pas d'indication du descripteur en attente, et il faut utiliser
le mécanisme habituel
(select(2),
poll(2),
read(2)
avec
O_NONBLOCK
configuré etc.)
pour déterminer quels descripteurs sont disponibles pour les E/S.
En sélectionnant un signal temps réel POSIX.1b (valeur >= SIGRTMIN), de
multiples événements d'E/S peuvent être mémorisés avec le même numéro.
Des informations supplémentaires sont disponibles, comme ci-dessus, si
SA_SIGINFO est configuré pour le gestionnaire.
En utilisant ces mécanismes, un programme peut implémenter des E/S totalement
asynchrones, la plupart du temps sans avoir besoin d'invoquer
select(2)
ou
poll(2).
L'utilisation de
O_ASYNC,
F_GETOWN,
est spécifique BSD et Linux.
F_GETSIG
et
F_SETSIG
sont spécifiques à Linux. POSIX disposent d'E/S asynchrones et de la structure
aio_sigevent
pour effectuer la même chose. Ceci est également disponible sous
Linux dans la bibliothèque GNU C (Glibc).
Bails
F_SETLEASE
et
F_GETLEASE
(depuis Linux 2.4) servent respectivement à établir et consulter le paramétrage
du bail dont le processus appelant dispose sur le fichier indiqué par
fd.
[NDT : Je traduis "lease" par "bail", faute de terme plus techique.]
Le bail sur un fichier fournit un mécanisme par lequel un processus détenteur du
bail est averti (par délivrance d'un signal) lorsqu'un autre
processus (le concurrent) essaye d'appeler
open(2)
ou
truncate(2)
sur ce fichier.
- F_SETLEASE
-
Fixe ou supprime un bail de fichier en fonction de la valeur
fournie dans l'entier
arg:
-
- F_RDLCK
-
Prendre un bail en lecture.
Le processus sera prévenu lorsqu'un autre processus
ouvrira le fichier en écriture ou le tronquera.
- F_WRLCK
-
Prendre un bail en écriture.
Le processus sera prévenu lorsqu'un autre processus
ouvrira le fichier (en lecture ou écriture) ou le tronquera.
Un bail en écriture ne peut être pris sur fichier que si aucun autre processus
ne l'a actuellement ouvert.
- F_UNLCK
-
Supprimer le bail sur un fichier.
Un processus ne peut prendre qu'un seul type de bail sur un fichier.
Les bails ne peuvent être pris que sur des fichiers normaux.
Un processus non-privilégié ne peut prendre un bail que sur un fichier dont
l'UID correspond au FS-UID du processus.
- F_GETLEASE
-
Indique le type de bail possédé sur le fichier
indiqué par
fd
en renvoyant
F_RDLCK, F_WRLCK, ou F_UNLCK,
pour signifiquer respectivement que le processus appelant a un bail en
lecture, écriture, ou pas de bail sur le fichier.
(Le troisième argument de
fcntl()
est omis).
Quand le concurrent appelle
open()
ou
truncate()
en conflit avec un bail établi par
F_SETLEASE,
l'appel-système est bloqué par le noyau (sauf si l'attribut
O_NONBLOCK
est indiqué avec
open(),
auquel cas il revient tout de suite avec l'erreur
EWOULDBLOCK).
Le noyau averti le processus tenant le bail par l'envoi d'un signal
(SIGIO par défaut).
Le tenant du bail doit répondre à ce signal en effectuant tout le
nettoyage nécessaire pour que le fichier soit accessible par un
autre processus (par ex. en vidant des buffers internes) et
en supprimant le bail en appelant la commande
F_SETLEASE
avec
arg
valant
F_UNLCK.
Si le détenteur du bail n'arrive pas à le libérer avant le nombre de secondes
indiqué dans
seconds specified in
/proc/sys/fs/lease-break-time
et si l'appel-système du concurrent reste bloqué
(il n'y avait pas d'option
O_NONBLOCK
durant l'appel
open(),
et l'appel-système n'a pas été interrompu par un gestionnaire de signal)
alors, le noyau va rompre de focre le bail du processus qui le tient.
Dès que le bail a été, de gré ou de force, résilié et en supposant
que le concurrent n'a pas débloqué son appel-système,
le noyau permet à se dernier de se dérouler.
Le signal de notification par défaut pour le tenant du bail est SIGIO,
mais on peut le modifier avec la commande
F_SETSIG
de la fonction
fcntl ().
Si une commande
F_SETSIG
est réalisée (même pour SIGIO), et si le gestionnaire de signal est installé
avec SA_SIGINFO, alors il recevra une
structure
siginfo_t
en second argument, et le champ
si_fd
contiendra le descripteur de fichier du bail où il y a
eu une tentative d'accès par un autre processus.
(Ceci sert si le processus tient des bails sur plusieurs fichiers).
Notification de modification de fichier et de répertoire
- F_NOTIFY
-
(nouveauté Linux 2.4)
Fournit un avertissement lorsque le répertoire correspondant à
fd
ou l'un des fichiers qu'il contient est modifié.
Les évènements à notifier sont précisé dans
arg,
sous forme de masque regroupant par un OU binaire zéro, une ou
plusieurs des constantes suivantes :
| Bit | Description (evenement dans le répertoire)
|
| DN_ACCESS |
| DN_MODIFY | Modification d'unfichier (write, pwrite,
|
| writev, truncate, ftruncate)
|
| DN_CREATE | Création d'un fichier (open, creat, mknod,
|
| mkdir, link, symlink, rename)
|
| DN_DELETE | Suppression d'un fichier (unlink, renommage
|
| dans un autre répertoire, rmdir)
|
| DN_RENAME | Un fichier a été renommé dans le même
|
| répertoire (rename)
|
| DN_ATTRIB | Les attributs d'un fichier ont été changés
|
| (chown, chmod, utime[s])
|
(Afin d'obtenir ces définitions, la macro _GNU_SOURCE_ doit être
définie avant l'inclusion de <fcntl.h>).
Les notifications de répertoire sont habituellement uniques, et l'application
doit ré-enregistrer une demande pour les notification ultérieures.
Inversement, si
DN_MULTISHOT
est incluse dans
arg,
les notifications resteront en effet jusqu'à une demande explicite de suppression.
Une série de
F_NOTIFY
sont cumulés, les évènements décrits dans
arg
étant ajoutés à l'ensemble des évènements déjà surveillés.
Pour supprimer les notifications de tous les évènement, il faut invoquer
F_NOTIFY
avec
arg
valant 0.
La notification se produit par l'occurence d'un signal.
Le signal par défaut est SIGIO, mais on peut le changer avec la commande
F_SETSIG
de
fcntl().
Dans ce cas, le gestionnaire de signal reçoit une structure
siginfo_t
en second argument (si le gestionnaire a été installé
avec SA_SIGINFO) dont le champ
si_fd
contient le descripteur du fichier qui a déclenché la notification
(utile pour superviser plusieurs
répertoires).
En outre, avec
DN_MULTISHOT,
un signal temps-réel POSIX.1b devrait être utilisé pour la notification
pour pouvoir empiler les notifications successives.
VALEUR RENVOYÉE
La valeur renvoyée par fcntl varie suivant le type d'opération :
- F_DUPFD
-
renvoie le nouveau descripteur.
- F_GETFD
-
renvoie l'attribut.
- F_GETFL
-
renvoie les attributs.
- F_GETOWN
-
renvoie le propriétaire du descripteur fichier.
- F_GETSIG
-
Valeur du signal envoyé lorsque la lecture ou l'écriture deviennent possibles,
ou zéro pour le comportement SIGIO traditionnel.
- Toutes les autres commandes
-
renvoient zéro.
En cas d'échec -1 est renvoyé, auquel cas
errno
contient le code d'erreur.
ERREURS
- EACCESS ou EAGAIN
-
L'opération est impossible à cause d'un verrou maintenu par un autre
processus. Ou l'opération est impossible à cause d'une projection en mémoire
effectuée par un autre processus.
- EBADF
-
fs
n'est pas un descripteur de fichier ouvert, ou la commande était
F_SETLK
ou
F_SETLKW
et le mode d'ouverture du descripteur de fichier ne correspond pas à celui
du type de verrou demandé.
- EDEADLK
-
Le verrouillage
F_SETLKW
conduirait à un blocage.
- EFAULT
-
lock
se trouve en dehors de l'espace d'adressage.
- EINTR
-
Pour
F_SETLKW,
la commande a été interrompue par un signal.
Pour
F_GETLK et F_SETLK,
la commande a été interrompue par un signal avant la vérification ou
l'acquisition du verrou. Se produit surtout lors d'un verrouillage distant
(par exemple à travers NFS), mais peut également arriver localement.
- EINVAL
-
Pour
F_DUPFD,
arg
est soit négatif, soit trop grand. Pour
F_SETSIG,
arg
n'est pas un numéro de signal correct.
- EMFILE
-
Pour
F_DUPFD,
le processus a déjà ouvert le nombre maximal de descripteurs de fichiers.
- ENOLCK
-
La table des verrous est pleine, ou le verrouillage distant
(par exemple via NFS) a échoué.
- EPERM
-
Essai d'effacement de l'attribut
O_APPEND
sur un fichier, mais il est considéré comme en-ajout-seulement.
NOTES
Les erreurs renvoyées par
dup2
ne sont pas les mêmes que celles renvoyées par
F_DUPFD.
Depuis le noyau 2.0, il n'y a pas d'interaction entre les verrous
placé par
flock(2)
et ceux de
fcntl(2).
POSIX 1003.1-2001 permet à
l_len
d'être négative (et si c'est le cas, l'intervalle décrivant le verrou
couvre les octets
l_start+l_len
jusqu'à
l_start-1
inclus). Toutefois pour les noyaux Linux actuels, l'appel-système
renvoie EINVAL dans ce cas.
Plusieurs systèmes ont d'autres champs dans
struct flock
comme, par exemple,
l_sysid.
Clairement,
l_pid
seul ne sera pas très utile si le processus tenant le verrou s'exécute
sur une autre machine.
CONFORMITÉ
SVr4, SVID, POSIX, X/OPEN, BSD 4.3. Seules les opérations F_DUPFD,
F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETLK, F_SETLK et F_SETLKW
sont spécifiées dans POSIX.1. F_GETOWN et F_SETOWN sont des BSDismes
non supportés par SVr4. F_GETSIG et F_SETSIG sont spécifiques à Linux.
F_NOTIFY, F_GETLEASE, et F_SETLEASE
sont spécifiques à Linux.
(Définissez la macro _GNU_SOURCE avant d'inclure <fcntl.h> pour avoir
ces définitions).
Les attributs autorisés pour F_GETFL/F_SETFL sont ceux supportés par
open(2)
et peuvent être différents suivant les systèmes.
O_APPEND, O_NONBLOCK, O_RDONLY, et O_RDWR sont spécifiés par POSIX.1.
SVr4 propose plusieurs autres options et attributs non documentés ici.
SVr4 indique des erreurs EIO, ENOLINK et EOVERFLOW supplémentaires.
VOIR AUSSI
dup2(2),
flock(2),
lockf(3),
open(2),
socket(2),
Voir aussi les fichiers locks.txt, mandatory.txt et dnotify.txt dans
la documentation du noyau.
TRADUCTION
Christophe Blaess, 1996-2003.
Index
- NOM
-
- SYNOPSIS
-
- DESCRIPTION
-
- Manipulation de Close-on-exec
-
- Attribut d'état du fichier
-
- Verrouillages coopératifs
-
- Verrouillage obligatoire
-
- Gestion des signaux
-
- Bails
-
- Notification de modification de fichier et de répertoire
-
- VALEUR RENVOYÉE
-
- ERREURS
-
- NOTES
-
- CONFORMITÉ
-
- VOIR AUSSI
-
- TRADUCTION
-
|