fcntl
Section: System Calls (2)
Updated: 5 février 2023
Index
Return to Main Contents
NOM
fcntl - Manipuler un descripteur de fichier
BIBLIOTHÈQUE
Bibliothèque C standard (libc, -lc)
SYNOPSIS
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
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.
fcntl() accepte un troisième paramètre optionnel. La nécessité de
fournir, ou pas, ce paramètre dépend de cmd. Le paramètre doit être du
type indiqué entre parenthèses après chaque nom de commande cmd (dans la
plupart des cas, le type requis est un int, et le paramètre est identifié
en utilisant le nom arg), ou void est indiqué si le paramètre n'est
pas nécessaire.
Certaines des opérations suivantes ne sont prises en charge qu’à partir
d’une version donnée du noyau Linux. La méthode préférée pour vérifier si le
noyau hôte prend en charge une certaine opération est d’invoquer fcntl()
avec la valeur de cmd voulue et ensuite de tester si l’appel a échoué
avec EINVAL, indiquant que le noyau ne reconnaît pas cette valeur.
Dupliquer un descripteur de fichier
- F_DUPFD (int)
-
Dupliquer le descripteur de fichier fd en utilisant le plus petit numéro
de descripteur de fichier libre supérieur ou égal à arg. Cela est
différent de dup2(2), qui utilise exactement le descripteur de fichier
transmis.
-
En cas de réussite, le nouveau descripteur de fichier est renvoyé.
-
Consultez dup(2) pour plus d'informations.
- F_DUPFD_CLOEXEC (int ; depuis Linux 2.6.24)
-
Comme pour F_DUPFD, mais positionner en plus l'attribut « close-on-exec »
pour le descripteur de fichier dupliqué. Indiquer cet attribut permet à un
programme d'éviter une opération F_SETFD de fcntl() supplémentaire
pour positionner l'attribut FD_CLOEXEC. Pour une explication sur ce en
quoi cet attribut est utile, consultez la description de O_CLOEXEC dans
open(2).
Attributs du descripteur de fichier
Les commandes suivantes manipulent les attributs associés à un descripteur
de fichier. Actuellement, un seul attribut est défini : il s'agit de
FD_CLOEXEC, l'attribut « close-on-exec ». Si le bit FD_CLOEXEC
est positionné, le descripteur de fichier sera automatiquement fermé lors
d'un execve(2) réussi (si execve(2) échoue, le descripteur de fichier
reste ouvert). Si le bit FD_CLOEXEC n'est pas positionné, le descripteur
de fichier restera ouvert à la fin d’un execve(2).
- F_GETFD (void)
-
Renvoyer (en tant que résultat de la fonction) les attributs du descripteur
de fichier ; arg est ignoré.
- F_SETFD (int)
-
Positionner les attributs du descripteur de fichier avec la valeur précisée
par arg.
Dans un programme multithreadé, l'utilisation simultanée dans un thread de
fcntl() avec F_SETFD afin de définir l'attribut « close-on-exec »
(FD_CLOEXEC), et de fork(2) suivi de execve(2) dans un autre thread
rend le programme vulnérable à une condition de concurrence pouvant
provoquer la divulgation du descripteur de fichier dans le programme exécuté
dans le processus enfant. Consultez les détails de l'attribut O_CLOEXEC
dans open(2) qui décrivent une solution à ce problème.
Attribut d'état du fichier
Un descripteur de fichier dispose de certains attributs d’état, initialisés
par open(2) et éventuellement modifiés par fcntl(). Les descripteurs
de fichier dupliqués (obtenus avec dup(2), fcntl(F_DUPFD),
fork(2), etc.) concernent la même description de fichier ouvert, et par
conséquent partagent les mêmes attributs d’état de fichier.
Les attributs et leurs sémantiques sont décrits dans la page open(2).
- F_GETFL (void)
-
Renvoyer (en tant que résultat de la fonction) les droits d'accès du fichier
et les drapeaux d'état du fichier ; arg est ignoré.
- F_SETFL (int)
-
Positionner les drapeaux d'état du fichier à la valeur indiquée par
arg. Les drapeaux des droits d'accès au fichier (O_RDONLY,
O_WRONLY, O_RDWR) et les attributs de création du fichier (O_CREAT,
O_EXCL, O_NOCTTY, O_TRUNC) de arg sont ignorés. Sous Linux,
cette commande ne peut changer que les attributs O_APPEND, O_ASYNC,
O_DIRECT, O_NOATIME et O_NONBLOCK. Modifier les attributs
O_DSYNC et O_SYNC est impossible, consultez BOGUES ci-dessous.
Verrouillages d’enregistrements coopératifs
Linux implémente les verrouillages d’enregistrements UNIX traditionnels
(« associés au processus »), tels que normalisés par POSIX. Pour une
alternative spécifique à Linux avec de meilleures sémantiques, consultez la
discussion suivante sur les verrouillages de description de fichier ouvert.
F_SETLK, F_SETLKW et F_GETLK servent à gérer les verrouillages
d'enregistrements (d’intervalle d’octets, de segments de fichiers ou de
zones de fichiers). Le troisième argument, lock, est un pointeur sur une
structure qui a au moins les champs suivants (dans un ordre non indiqué).
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
(mis par F_GETLK et F_OFD_GETLK seulement) */
...
};
Les champs l_whence, l_start et l_len de cette structure indiquent
l'intervalle d'octets à verrouiller. Des octets après la fin du fichier
peuvent être verrouillés, mais pas des octets avant le début du fichier.
l_start est la position de début du verrou, et est interprété de façon
relative : au début du fichier (si l_whence vaut SEEK_SET) ; à la
position actuelle dans le fichier (si l_whence vaut SEEK_CUR) ; à la
fin du fichier (si l_whence vaut SEEK_END). Dans les deux derniers
cas, l_start peut être un nombre négatif, à partir du moment où la
position fournie ne pointe pas avant le début du fichier.
l_len indique le nombre d'octets à verrouiller. Si l_len est positif,
alors l'intervalle à verrouiller couvre les octets à partir de l_start
jusqu'à l_start+l_len-1 (inclus). Indiquer 0 dans l_len a une
signification particulière : cela verrouille tous les octets à partir de la
position indiquée par l_whence et l_start jusqu'à la fin du fichier,
quelle que soit la taille que prendra le fichier.
POSIX.1-2001 permet (mais n'impose pas) à une implémentation de prendre en
charge des valeurs de l_len négatives ; si l_len est négatif,
l'intervalle décrivant le verrou lock couvre les octets
l_start+l_len jusqu'à l_start-1 inclus. Cela est géré par
Linux 2.4.21 et Linux 2.5.49.
Le champ l_type peut servir à placer un verrou en lecture (F_RDLCK) ou
en écriture (F_WRLCK) sur un fichier. Un nombre quelconque de processus
peuvent tenir un verrou en lecture (partagé), sur une zone 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 zone
d'un fichier ; si un nouveau verrou est appliqué sur une zone déjà
verrouillée, alors le verrou précédent est converti suivant le nouveau
type. Ces conversions pourraient entraîner le découpage, la réduction ou
l'extension du verrou existant si le nombre d'octets du nouveau verrou ne
coïncide pas exactement avec celui de l'ancien.
- F_SETLK (struct flock *)
-
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 (l’erreur renvoyée
dans ce cas dépend des implémentations, donc POSIX impose aux applications
portables de vérifier les deux erreurs).
- F_SETLKW (struct flock *)
-
Comme F_SETLK, mais attendre la libération du verrou au lieu de renvoyer
une erreur si un verrou en conflit est utilisé sur le fichier. Si un signal
est reçu pendant l'attente, l'appel est interrompu et renverra immédiatement
(après le retour du gestionnaire de signaux) la valeur -1. errno sera
remplie avec la valeur EINTR ; consultez signal(7).
- F_GETLK (struct flock *)
-
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êchaient 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. Si le
verrouillage en conflit est un verrouillage d’enregistrements UNIX
traditionnels (« associé au processus »), alors le champ l_pid est défini
avec le PID du processus détenant ce verrou. Si le verrouillage en conflit
est un verrouillage de description de fichier ouvert, alors l_pid est
défini à -1. Remarquez que les renseignements renvoyés pourraient déjà
être périmés au moment ou l’appelant les inspecte.
Pour pouvoir placer un verrou en lecture, fd doit être ouvert au moins en
lecture. Pour placer un verrou en écriture, fd doit être ouvert en
écriture. Pour placer les deux types de verrous, il faut une ouverture en
lecture/écriture.
Lors du placement de verrous avec F_SETLKW, le noyau détecte les
interblocages (deadlocks), au moyen desquels au moins deux processus ont
leurs demandes de verrouillage réciproquement bloquées par des verrous
détenus par d’autres processus. Par exemple, supposons qu’un processus A
détient un verrou d’écriture sur l’octet 100 d’un fichier et qu’un processus
B détient un verrou d’écriture sur l’octet 200. Si les deux processus
tentent alors de verrouiller l’octet déjà verrouillé par l’autre processus
en utilisant F_SETLKW, alors, sans détection d’interblocage, les deux
processus resteront bloqués indéfiniment. Quand le noyau détecte ce type
d’interblocages, il force l’une des demandes bloquantes de verrouillage à
échouer immédiatement avec l’erreur EDEADLK ; une application qui
rencontre ce type d’erreur devrait libérer certains de ses verrous pour
permettre à d’autres applications de continuer avant de tenter d’obtenir de
nouveau les verrous dont elle a besoin. Les interblocages circulaires,
impliquant plus de deux processus, sont également détectés. Remarquez,
cependant, que l’algorithme de détection d’interblocages du noyau a ses
limites, consultez BOGUES.
Outre la suppression par un F_UNLCK explicite, les verrous sont
automatiquement libérés lorsque le processus se termine.
Les verrouillages d'enregistrements ne sont pas hérités par les enfants lors
d'un fork(2), mais sont conservés à la fin d'un execve(2).
À cause des tampons gérés par la bibliothèque stdio(3), l'utilisation des
verrous d'enregistrements avec les routines de celle-ci est
déconseillée. Utilisez plutôt read(2) et write(2).
Les verrouillages d'enregistrements décrits précédemment sont associés au
processus (contrairement aux verrouillages de description de fichier ouvert
décrits ci-dessous). Cela a quelques conséquences malheureuses.
- •
-
Si le processus ferme l'un des descripteurs se référant à un fichier,
alors tous les verrous du processus sur ce fichier sont libérés, quels que
soient le ou les descripteurs de fichier sur lesquels les verrous avaient
été obtenus. C'est dangereux : cela signifie qu'un processus peut perdre
ses verrous sur un fichier comme /etc/passwd ou /etc/mtab si, pour une
raison quelconque, une fonction de bibliothèque décide d’ouvrir, lire, puis
refermer le même fichier.
- •
-
Les threads d’un processus partagent les verrous. Autrement dit, un
programme multithreadé ne pas pas utiliser de verrouillage d’enregistrement
pour s’assurer que les threads ne vont pas accéder simultanément à la même
zone d’un fichier.
Les verrouillages de description de fichier ouvert apportent une solution à
ces deux problèmes.
Verrouillages de description de fichier ouvert (non POSIX)
Les verrouillages de description de fichier ouvert sont des verrouillages
d’intervalle d’octets coopératifs dont le fonctionnement est identique en
presque tout point aux verrouillages d’enregistrements traditionnels décrits
précédemment. Ce type de verrouillage est spécifique à Linux et disponible
depuis la version 3.15. Pour une explication des descriptions de fichier
ouvert, consultez open(2).
La principale différence entre les deux types de verrouillage est que les
verrouillages d’enregistrements traditionnels sont associés à un processus,
alors que les verrouillages de description de fichier ouvert sont associés à
la description de fichier ouvert sur laquelle ils sont obtenus, tout comme
les verrous obtenus avec flock(2). Par conséquent (et contrairement aux
verrouillages d’enregistrements coopératifs traditionnels), les
verrouillages de description de fichier ouvert sont hérités entre fork(2)
(et clone(2) avec CLONE_FILES) et ne sont automatiquement libérés que
lors de la dernière fermeture de la description de fichier ouvert, au lieu
d’être libérés lors de n’importe quelle fermeture du fichier.
Les combinaisons de verrouillage de conflit (à savoir un verrouillage en
lecture et en écriture, ou deux verrouillages en écriture), où l'un est un
verrouillage de description de fichier ouvert, et l'autre un verrouillage
traditionnel d'enregistrement sont toujours en conflit même lorsqu'ils sont
acquis par le même processus sur le même descripteur de fichier.
Les verrouillages de description de fichier ouvert placés à l’aide de la
même description de fichier ouvert (c’est-à-dire à l’aide du même
descripteur de fichier ou à l’aide d’un descripteur de fichier dupliqué par
fork(2), dup(2), fcntl(2) F_DUPFD, etc.) sont toujours
compatibles : si un nouveau verrou est placé sur une zone déjà verrouillée,
alors le verrou existant est converti suivant le nouveau (ces conversions
pourraient avoir pour conséquence le découpage, la réduction ou l'extension
du verrou existant comme évoqué précédemment).
En revanche, les verrouillages de description de fichier ouvert peuvent être
en conflit entre eux quand ils sont obtenus à l’aide de descriptions de
fichier ouvert différentes. Ainsi, les threads dans un programme
multithreadé peuvent utiliser des verrouillages de description de fichier
ouvert pour synchroniser l’accès à une zone de fichier si tous les threads
réalisent leur propre appel d’open(2) sur le fichier et utilisent les
verrouillages à l’aide du descripteur de fichier qui en résulte.
Comme avec les verrouillages coopératifs traditionnels, le troisième
argument de fcntl(), lock, est un pointeur vers une structure
flock. Contrairement aux verrouillages d’enregistrements traditionnels,
le champ l_pid de cette structure doit être mis à zéro lors de
l’utilisation des commandes décrites ci-dessous.
Les commandes permettant d’interagir avec les verrouillages de description
de fichier ouvert sont similaires à celles utilisées avec les verrouillages
traditionnels.
- F_OFD_SETLK (struct flock *)
-
Acquérir (si l_type vaut F_RDLCK ou F_WRLCK) ou libérer (si
l_type vaut F_UNLCK) un verrou de description de fichier ouvert sur
les octets indiqués par les champs l_whence, l_start et l_len de
lock. Si un conflit avec un verrou détenu par un autre processus existe,
cet appel renvoie -1 et définit errno à EAGAIN.
- F_OFD_SETLKW (struct flock *)
-
Comme F_OFD_SETLK, mais si un verrou en conflit existe sur le fichier
attendre la libération du verrou. Si un signal à intercepter est reçu
pendant l'attente, l'appel est interrompu et renverra immédiatement (après
renvoi du gestionnaire de signaux) la valeur -1 et errno sera définie
à EINTR ; consultez signal(7).
- F_OFD_GETLK (struct flock *)
-
En entrée dans cette routine, lock décrit un verrou de description de
fichier ouvert 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êchaient
l'action, alors des informations sur l'un de ces verrous sont renvoyés à
l’aide de lock, comme décrit précédemment pour F_GETLK.
Dans l’implémentation actuelle, aucune détection d’interblocage n’est
réalisée pour les verrouillages de description de fichier ouvert
(contrairement aux verrouillages d’enregistrements associés au processus,
pour lesquels le noyau réalise une détection d’interblocage).
Verrouillage impératif
Attention : l'implémentation Linux du verrouillage obligatoire n'est pas
fiable. Voir BOGUES ci-dessous. À cause de ces bogues et du fait que cette
fonction soit vue comme peu utilisée, depuis Linux 4.5, le verrouillage
obligatoire est devenu une fonction facultative gérée par une option de
configuration (CONFIG_MANDATORY_FILE_LOCKING). Cette fonctionnalité n'est
plus prise en charge depuis Linux 5.15 et supérieur.
Par défaut, à la fois les verrouillages d’enregistrements traditionnels
(associés au processus) et ceux de description de fichier ouvert sont
coopératifs. Les verrouillages coopératifs ne sont pas imposés, donc ils ne
fonctionnent qu'entre processus qui les utilisent.
Les deux types de verrouillages peuvent aussi être impératifs. Les verrous
impératifs sont appliqués à tous les processus. Si un processus tente
d'effectuer un accès incompatible (par exemple read(2) ou write(2))
sur une zone d'un fichier qui a un verrou impératif, le résultat dépend de
l'attribut O_NONBLOCK du descripteur de fichier. S'il n'est pas activé,
l'appel système est bloqué jusqu'à ce que le verrou soit enlevé ou converti
en un mode compatible avec l'accès demandé. Si l'attribut O_NONBLOCK est
activé, l'appel système échoue avec l'erreur EAGAIN.
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)), ou l'attribut
MS_MANDLOCK de mount(2). Le verrouillage impératif est activé pour un
fichier en désactivant la permission d'exécution du groupe et en activant le
bit de permission Set-GID (consultez chmod(1) et chmod(2)).
Le verrouillage impératif n’est pas défini par POSIX. Certains autres
systèmes permettent également d’utiliser le verrouillage impératif, mais la
façon de l’activer dépend des systèmes.
Verrouillages perdus
Quand un verrou d'observation est obtenu sur un système de fichiers en
réseau comme NFS, il est possible que le verrou soit perdu. Cela peut
arriver suite à une action d'administration sur le serveur ou à une
partition du réseau (à savoir une perte de la connexion réseau avec le
serveur) qui dure assez pour que le serveur pense que le client ne
fonctionne plus.
Quand un système de fichiers détermine qu'un verrou est perdu, les futures
requêtes read(2) ou write(2) peuvent échouer avec l'erreur
EIO. Cette erreur persistera jusqu'à la suppression du verrou ou la
fermeture du descripteur de fichier. Depuis Linux 3.12, cela se produit au
moins sur NFSv4 (y compris toutes les versions mineures).
Certaines versions d'UNIX envoient un signal (SIGLOST) dans ce cas. Linux
ne définit pas ce signal et il ne fournit pas de notification asynchrone de
perte de verrous.
Gestion des signaux
F_GETOWN, F_SETOWN, F_GETOWN_EX, F_SETOWN_EX, F_GETSIG et
F_SETSIG servent à gérer les signaux de disponibilité d'entrée-sortie :
- F_GETOWN (void)
-
Renvoyer (comme résultat de la fonction) le PID ou l'ID de processus qui
reçoit les signaux SIGIO et SIGURG pour les événements concernant le
descripteur de fichier fd. Les ID de processus sont renvoyés sous forme
de valeurs positives ; les ID de groupe de processus sont renvoyés sous
forme de valeurs négatives (mais consultez la section BOGUES
ci-dessous). arg est ignoré.
- F_SETOWN (int)
-
Définir le PID ou l'identifiant de processus qui recevront les signaux
SIGIO et SIGURG pour les événements concernant le descripteur
fd. L'ID de processus ou de groupe de processus cible est indiqué dans
arg. L'ID d'un processus est indiqué sous forme d'une valeur positive ;
l'ID d'un groupe de processus est formulé en tant que valeur négative. En
général, le processus appelant indique son propre PID comme argument (arg
est donc getpid(2)).
-
Outre la définition du propriétaire du descripteur de fichier, vous pourriez
aussi activer la génération de signaux sur le descripteur de fichier. Cela
se fait en utilisant la commande F_SETFL de fcntl() pour positionner
le drapeau d'état du fichier O_ASYNC sur le descripteur de fichier. Par
conséquent, un signal SIGIO est envoyé dès que l'entrée ou la sortie sont
possibles sur ce descripteur. La commande F_SETSIG de fcntl() peut
être utilisée pour recevoir un autre signal que SIGIO.
-
L'envoi d'un signal au processus (ou groupe de processus) propriétaire
indiqué par F_SETOWN est conditionné par les mêmes vérifications de
permissions que l'envoi d'un signal par kill(2), où le processus envoyant
le signal est celui qui utilise F_SETOWN (mais consultez la section
BOGUES ci-dessous). Si cette vérification échoue, le signal est ignoré
silencieusement. Note : l'opération F_SETOWN enregistre les droits de
l'appelant utilisés lors de l'appel fcntl() pour les vérifications de
permissions.
-
Si le descripteur fd est un socket, F_SETOWN permet également la
réception de signaux SIGURG lorsque des données hors-bande arrivent
sur le socket. (SIGURG est émis dans toutes les situations où l'appel
select(2) aurait indiqué que le socket est dans une « situation
exceptionnelle ».)
-
Le paragraphe ci-dessous était pertinent Linux 2.6.x, jusqu'à Linux 2.6.11
inclus :
-
-
Si une valeur non nulle est passée à F_SETSIG dans un processus
multithreadé utilisant une bibliothèque de threads gérant les groupes de
threads (par exemple NPTL), une valeur positive passée à F_SETOWN a une
signification différente : au lieu d'être un PID identifiant tout un
processus, il s'agit d'un identifiant de thread, référant à un thread
spécifique dans un processus. Par conséquent, il peut être nécessaire de
passer à F_SETOWN la valeur renvoyée par gettid(2) plutôt que celle
renvoyée par getpid(2) pour obtenir les résultats souhaités si
F_SETSIG est utilisé. (Dans les implémentations actuelles des threads
sous Linux, l'identifiant de thread (TID) du thread principal est son
identifiant de processus. Cela signifie qu'un processus avec un seul thread
peut utiliser indifféremment gettid(2) ou getpid(2).) Veuillez
toutefois noter que les remarques de ce paragraphe ne s'appliquent pas au
signal SIGURG généré lorsque des données hors-bande sont disponibles
sur un socket : ce signal est toujours envoyé soit à un processus, soit à
un groupe de processus, selon la valeur donnée à F_SETOWN.
-
Le comportement ci-dessus a été supprimé par accident dans Linux 2.6.12, et
ne sera pas remis. À partir de Linux 2.6.32, utilisez F_SETOWN_EX pour
envoyer les signaux SIGIO et SIGURG à un thread en particulier.
- F_GETOWN_EX (struct f_owner_ex *) (depuis Linux 2.6.32)
-
Renvoyer les paramètres du propriétaire du descripteur de fichier actuel,
tels que définis par une utilisation antérieure de
F_SETOWN_EX. L'information est renvoyée dans la structure pointée par
arg, qui a la forme suivante :
-
struct f_owner_ex {
int type;
pid_t pid;
};
-
Le champ type aura l'une des valeurs F_OWNER_TID, F_OWNER_PID ou
F_OWNER_PGRP. Le champ pid est un entier positif représentant un
identifiant de thread, de processus ou de groupe de processus. Consultez
F_SETOWN_EX pour plus de détails.
- F_SETOWN_EX (struct f_owner_ex *) (depuis Linux 2.6.32)
-
Cette opération effectue une tâche similaire à F_SETOWN. Elle autorise
l'appelant à diriger les signaux de disponibilité d'entrées-sorties vers un
thread, un processus ou un groupe de processus spécifiques. L'appellant
indique le destinataire des signaux avec arg, qui est un pointeur vers
une structure f_owner_ex. Le champ type possède l'une des valeurs
suivantes, qui définit comment pid est interprété :
-
- F_OWNER_TID
-
Envoyer le signal au thread dont l'identifiant (la valeur renvoyée par un
appel à clone(2) ou gettid(2)) est indiqué par pid.
- F_OWNER_PID
-
Envoyer le signal au processus dont l'identifiant est indiqué par pid.
- F_OWNER_PGRP
-
Envoyer le signal au groupe de processus dont l'identifiant est indiqué par
pid. Notez que, à la différence de F_SETOWN, un identifiant de groupe
de processus est indiqué ici avec une valeur positive.
- F_GETSIG (void)
-
Renvoyer (comme résultat de la fonction) 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. arg est ignoré.
- F_SETSIG (int)
-
Définir le signal à émettre lorsque l'entrée ou la sortie deviennent
possibles à la valeur fournie par arg. 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_SETSIG avec une valeur non nulle, et en configurant
SA_SIGINFO pour le gestionnaire (consultez sigaction(2)), des
informations supplémentaires sur les événements d'entrées-sorties 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 de descripteurs de fichier en attente, et il faut utiliser les
mécanismes habituels (select(2), poll(2), read(2) avec
O_NONBLOCK configuré, etc.) pour déterminer quels descripteurs de fichier
sont disponibles pour les entrées-sorties.
-
Remarquez que le descripteur de fichier fourni dans si_fd est celui
indiqué lors de l'opération F_SETSIG. Cela peut provoquer un effet de
bord inhabituel. Si le descripteur de fichier est dupliqué (dup(2) ou
équivalent), et si le descripteur de fichier d'origine est fermé, alors des
événements E/S continueront à être émis mais le champ si_fd contiendra le
numéro du descripteur de fichier à présent fermé.
-
En sélectionnant un signal temps réel (valeur >= SIGRTMIN), de
multiples événements d'entrées-sorties peuvent être mémorisés avec le même
numéro (la mémorisation dépend de la mémoire disponible). Des informations
supplémentaires sont disponibles, comme ci-dessus, si SA_SIGINFO est
configuré pour le gestionnaire.
-
Notez que Linux impose une limite sur le nombre de signaux temps réel qui
peuvent être mis en attente pour un processus (consultez getrlimit(2) et
signal(7)), et si cette limite est atteinte, le noyau change de
comportement et envoie SIGIO, et ce signal est délivré au processus
entier plutôt qu'au thread spécifique.
En utilisant ces mécanismes, un programme peut implémenter des
entrées-sorties totalement asynchrones, la plupart du temps sans avoir
besoin d'invoquer select(2) ou poll(2).
L'utilisation de O_ASYNC est spécifique à BSD et Linux. La seule
utilisation de F_GETOWN et F_SETOWN spécifiée dans POSIX.1 est en
conjonction avec l’utilisation du signal SIGURG sur les sockets (POSIX ne
spécifie pas le signal SIGIO). F_GETOWN_EX, F_SETOWN_EX,
F_GETSIG et F_SETSIG sont spécifiques à Linux. POSIX dispose
d'entrées-sorties asynchrones et de la structure aio_sigevent pour
effectuer la même chose. Cela est également disponible sous Linux dans la
bibliothèque GNU C (glibc).
Baux
F_SETLEASE et F_GETLEASE (depuis Linux 2.4) servent respectivement à
établir un nouveau bail et à consulter le bail actuel sur le descripteur de
fichier indiqué par fd. (NdT : je traduis « lease » par « bail »,
faute de terme plus technique.) 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 « casseur de bail ») essaie
d'appeler open(2) ou truncate(2) sur le fichier vers lequel pointe ce
descripteur de fichier.
- F_SETLEASE (int)
-
Définir ou supprimer un bail de fichier en fonction de la valeur fournie
dans l'entier arg :
-
- F_RDLCK
-
Prendre un bail en lecture. Le processus appelant sera prévenu lorsqu'un
autre processus ouvrira le fichier en écriture ou le tronquera. Un bail en
lecture ne peut être placé que sur un descripteur de fichier ouvert en
lecture seule.
- F_WRLCK
-
Prendre un bail en écriture. Le processus appelant 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 le fichier que s'il n'y
a aucun autre descripteur de fichier ouvert pour le fichier.
- F_UNLCK
-
Supprimer le bail sur un fichier.
Les baux sont associés à une description de fichier ouvert (consultez
open(2)). Cela signifie que les descripteurs de fichier dupliqués (créés
par, par exemple, fork(2) ou dup(2)) font référence au même bail, et
que ce bail peut être modifié ou résilié par n'importe lequel de ces
descripteurs. De plus, le bail est résilié soit par une opération F_UNLCK
explicite sur n'importe lequel de ces descripteurs dupliqués, soit lorsque
tous ces descripteurs ont été fermés.
Les baux 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 (le
propriétaire) correspond au FS-UID du processus. Un processus possédant la
capacité CAP_LEASE peut prendre un bail sur n'importe quel fichier.
- F_GETLEASE (void)
-
Indiquer le type de bail possédé sur le descripteur de fichier fd en
renvoyant F_RDLCK, F_WRLCK, ou F_UNLCK, signifiant respectivement
que le processus appelant a un bail en lecture, écriture, ou pas de bail sur
le fichier. arg est ignoré.
Lorsqu'un processus (le « casseur de bail ») appelle open(2) ou
truncate(2) en conflit avec un bail établi par F_SETLEASE, l'appel
système est bloqué par le noyau et le noyau avertit 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 exemple en vidant des
tampons internes) et en supprimant ou déclassant son bail. Un bail est
supprimé en appelant la commande F_SETLEASE avec arg valant
F_UNLCK. Si le tenant du bail possède un bail en écriture sur le fichier
et que le casseur de bail ouvre le fichier en lecture, il est suffisant que
le tenant du bail déclasse le bail en un bail en lecture. Cela est effectué
en appelant la commande F_SETLEASE avec arg valant F_RDLCK.
Si le détenteur du bail n'arrive pas à le déclasser ou le supprimer avant le
nombre de secondes indiqué dans /proc/sys/fs/lease-break-time alors le
noyau supprimera ou déclassera de force le bail du processus qui le détient.
Dès qu'un cassage de bail a été commencé, F_GETLEASE renvoie le type de
bail cible (F_RDLCK ou F_UNLCK, en fonction de ce qui serait
compatible avec le casseur de bail) jusqu'à ce que le détenteur du bail ne
le déclasse ou le supprime volontairement, ou que le noyau ne soit forcé à
le faire après expiration du délai de cassage de bail.
Dès que le bail a été, de gré ou de force, résilié ou déclassé et en
supposant que le casseur de bail n'a pas débloqué son appel système, le
noyau permet à ce dernier de se dérouler.
Si l'appel à open(2) ou truncate(2) du casseur de bail est interrompu
par un gestionnaire de signal, l'appel système échoue avec l'erreur
EINTR, mais les autres étapes décrites ci-dessous se déroulent
normalement. Si le casseur de bail est tué par un signal pendant que son
appel système open(2) ou truncate(2) bloque, tout se déroule comme
décrit ci-dessus. De même, si le casseur de bail utilise l'option
O_NONBLOCK de open(2), l'appel retourne immédiatement avec l'erreur
EWOULDBLOCK, mais les autres étapes se déroulent comme décrit
ci-dessus.
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. (Cela sert si le processus tient des baux
sur plusieurs fichiers.)
Notification de modification de fichier et de répertoire (dnotify)
- F_NOTIFY (int)
-
(Depuis Linux 2.4) Fournir 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és dans arg, sous forme de masque
regroupant par un OU binaire zéro, une ou plusieurs des constantes
suivantes :
-
- DN_ACCESS
-
Accès à un fichier (read(2), pread(2), readv(2) et similaires)
- DN_MODIFY
-
Modification d'un fichier (write(2), pwrite(2), writev(2),
truncate(2), ftruncate(2) et similaires).
- DN_CREATE
-
Création d'un fichier (open(2), creat(2), mknod(2), mkdir(2),
link(2), symlink(2), rename(2) dans ce répertoire).
- DN_DELETE
-
Suppression d'un fichier (unlink(2), rename(2) dans un autre
répertoire, rmdir(2)).
- DN_RENAME
-
Un fichier a été renommé dans le même répertoire (rename(2)).
- DN_ATTRIB
-
Les attributs d'un fichier ont été modifiés (chown(2), chmod(2),
utime(2), utimensat(2) et similaires).
-
(Afin d'obtenir ces définitions, la macro _GNU_SOURCE doit être définie
avant d'inclure tout fichier d'en-tête).
-
Les notifications de répertoire sont habituellement uniques, et
l'application doit réenregistrer une demande pour les notifications
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énements, il faut invoquer F_NOTIFY avec
arg valant 0.
-
La notification se produit par l'occurrence d'un signal. Le signal par
défaut est SIGIO, mais on peut le changer avec la commande F_SETSIG de
fcntl() (remarquez que SIGIO est un des signaux standards sans file
d’attente ; basculer vers l’utilisation d’un signal temps réel signifie que
plusieurs notifications peuvent être mises en attente dans le
processus). 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 devrait être utilisé
pour la notification pour pouvoir empiler les notifications successives.
-
Remarque : les nouvelles applications devraient utiliser l'interface
inotify (disponible depuis Linux 2.6.13), qui fournit une bien meilleure
interface pour obtenir des notifications d'événements sur le système de
fichiers. Consultez inotify(7).
Changer la capacité d'un tube
- F_SETPIPE_SZ (int ; depuis Linux 2.6.35)
-
Changer la capacité du tube référencé par fd pour contenir au moins
arg octets. Un processus non privilégié peut ajuster la capacité d'un
tube à toute valeur comprise entre la taille de page du système et la limite
définie dans /proc/sys/fs/pipe-max-size (consultez proc(5)). Les
tentatives pour définir la capacité du tube en dessous de la taille de page
sont silencieusement arrondies à la taille de page. Les tentatives d'un
processus non privilégié pour définir la capacité du tube au dessus de
/proc/sys/fs/pipe-max-size renvoie l'erreur EPERM ; un processus
privilégié (CAP_SYS_RESOURCE) peut passer outre cette limite.
-
Lors de l'affectation d'un tampon à un tube, le noyau peut utiliser une
capacité supérieure à arg, si c'est plus pratique pour l'implémentation
(dans l'implémentation actuelle, l'affectation se fait sur le prochain
multiple de la taille de la page supérieur à la puissance de deux de la
taille indiquée). La capacité actuelle (en octets) définie est renvoyée en
tant que résultat de la fonction.
-
Essayer de définir une capacité de tube plus petite que la taille de
l'espace du tampon actuellement utilisé pour stocker des données aboutit à
l'erreur EBUSY.
-
Remarquez qu'à cause de la manière dont les pages du tampon du tube sont
utilisées quand des données sont écrites dans le tube, le nombre d'octets
qui peuvent être écrits peut être inférieur à la taille nominale, selon la
taille des écritures.
- F_GETPIPE_SZ (void ; depuis Linux 2.6.35)
-
Renvoyer (comme résultat de la fonction) la capacité du tube référencé par
fd.
Verrouillages de fichier
Les verrous de fichier limitent le jeu d'opérations autorisées sur un
fichier donné. Pour chaque verrou positionné sur un fichier, un ensemble
spécifique d'opérations échouera sur le fichier avec EPERM à partir de
maintenant. Le fichier est dit verrouillé (sealed). Le jeu de verrous dépend
du type de fichier et du système de fichiers sous-jacents. Pour un aperçu du
verrouillage de fichiers, un point sur ses objectifs et des exemples de
code, voir memfd_create(2).
Actuellement, les verrous de fichier ne peuvent être appliqués que sur un
descripteur de fichier renvoyé par memfd_create(2) (si
MFD_ALLOW_SEALING est utilisé). Sur d'autres systèmes de fichiers, toutes
les opérations de fcntl() agissant sur les verrous renverront EINVAL.
Les verrous constituent une propriété d'un inœud. Ainsi, tous les
descripteurs de fichier ouverts qui se rapportent au même inœud partagent le
même jeu de verrous. En outre, les verrous ne peuvent jamais être supprimés
mais uniquement ajoutés.
- F_ADD_SEALS (int ; depuis Linux 3.17)
-
Ajouter les verrous donnés dans le paramètre arg du masque de bit à
l'ensemble de verrous de l'inœud auquel se rapporte le descripteur de
fichier fd. Les verrous ne peuvent pas être supprimés de nouveau. Une
fois que cet appel réussit, ils sont renforcés immédiatement par le
noyau. Si le jeu de verrous actuel comprend F_SEAL_SEAL (voir
ci-dessous), cet appel sera rejeté avec EPERM. L'ajout d'un verrou déjà
défini n'est pas opérationnel, si F_SEAL_SEAL n'est pas déjà
positionné. Pour positionner un verrou, le descripteur de fichier fd doit
être accessible en écriture.
- F_GET_SEALS (void ; depuis Linux 3.17)
-
Renvoyer (en tant que résultat de la fonction) le jeu de verrous actuel de
l'inœud auquel se rapporte fd. Si aucun verrou n'est positionné, 0 est
renvoyé. Si le fichier ne gère pas les verrous, -1 est renvoyé et
errno est positionné sur EINVAL.
Les verrous suivants sont disponibles :
- F_SEAL_SEAL
-
Si ce verrou est positionné, tout appel suivant à fcntl() avec
F_ADD_SEALS échouera avec l'erreur EPERM. Ce verrou empêche donc toute
modification du jeu de verrous lui-même. Si le jeu de verrous initial du
fichier comprend F_SEAL_SEAL, cela le rend en fait constant et
verrouillé.
- F_SEAL_SHRINK
-
Si ce verrou est positionné, le fichier en question ne peut pas voir sa
taille réduite. Cela concerne open(2) avec le drapeau O_TRUNC ainsi
que truncate(2) et ftruncate(2). Ces appels échouent avec EPERM si
vous essayez de réduire le fichier en question. Augmenter la taille reste
possible.
- F_SEAL_GROW
-
Si ce verrou est positionné, le fichier en question ne peut pas voir sa
taille augmentée. Cela concerne write(2) après la fin du fichier,
truncate(2), ftruncate(2) et fallocate(2). Ces appels échoueront
avec EPERM si vous les utilisez pour augmenter la taille du fichier. Si
vous la laissez stable ou la réduisez, ces appels fonctionneront comme
prévu.
- F_SEAL_WRITE
-
Si ce verrou est positionné, vous ne pouvez pas modifier le contenu du
fichier. Remarquez que la réduction ou l'augmentation de la taille du
fichier restent possibles et autorisées. Ainsi, ce verrou s'utilise en
principe avec un autre verrou. Il concerne write(2) et fallocate(2)
(combiné au drapeau FALLOC_FL_PUNCH_HOLE). Ces appels échoueront avec
EPERM si ce verrou est positionné. De plus, les tentatives de créer de
nouveaux tableaux de mémoire (memory-mappings) accessibles en écriture avec
mmap(2) échoueront également avec EPERM.
-
L'utilisation de l'opération F_ADD_SEALS pour définir le verrou
F_SEAL_WRITE échoue avec EBUSY si un tableau partagé accessible en
écriture existe. De tels tableaux doivent être désassociés avant d'ajouter
ce verrou. De plus, s'il existe des opérations d'E/S asynchrones
(io_submit(2)) en attente sur le fichier, toutes les écritures
postérieures seront ignorées.
- F_SEAL_FUTURE_WRITE (depuis Linux 5.1)
-
L'effet de ce verrou est identique à F_SEAL_WRITE, mais le contenu du
fichier peut encore être modifié avec des tableaux partagés accessibles en
écriture créés avant que le verrou ne soit positionné. Toute tentative de
créer de nouveaux tableaux accessibles en écriture sur le fichier avec
mmap(2) échouera avec EPERM. De même, une tentative d'écriture dans le
fichier avec write(2) échouera avec EPERM.
-
En utilisant ce verrou, un processus peut créer un tampon de mémoire qu'il
peut continuer à modifier tout en le partageant sur une base de « lecture
seule » avec d'autres processus.
Indications de lecture/écriture de fichiers
Les indications (hints) de durée d’écriture peuvent être utilisées pour
informer le noyau de la durée relative prévue des écritures sur un inœud ou
à l’aide d’une description de fichier ouvert en particulier (voir open(2)
pour une explication sur les descriptions de fichier ouvert). Dans ce
contexte, le terme « durée d'écriture » (write lifetime) signifie la durée
prévue de vie des données sur le média avant d'être remplacées ou écrasées.
Une application peut utiliser les différentes valeurs de référence indiquées
ci-dessous pour séparer les écritures en différentes classes, pour que
plusieurs utilisateurs ou applications fonctionnant sur un seul dorsal de
stockage puissent agréger leurs motifs E/S de manière cohérente. Cependant,
il n'existe pas de sémantique fonctionnelle impliquée par ces attributs et
plusieurs classes E/S peuvent utiliser les valeurs de référence de durée
d'écriture de manière arbitraire, tant que celles-ci sont utilisées de
manière cohérente.
Les opérations suivantes peuvent être appliquées au descripteur de fichier,
fd :
- F_GET_RW_HINT (uint64_t * ; depuis Linux 4.13)
-
Renvoie la valeur de référence (« hint ») de lecture/écriture associée à
l'inœud sous-jacent auquel renvoie fd.
- F_SET_RW_HINT (uint64_t * ; depuis Linux 4.13)
-
Définit la valeur de référence de lecture/écriture associée à l'inœud
sous-jacent auquel renvoie fd. Cette valeur de référence persiste soit
jusqu'à être explicitement modifiée, soit jusqu'à ce que le système de
fichiers sous-jacent ne soit démonté.
- F_GET_FILE_RW_HINT (uint64_t * ; depuis Linux 4.13)
-
Renvoie la valeur de référence « hint » de lecture/écriture associée à la
description de fichier ouvert à laquelle renvoie fd.
- F_SET_FILE_RW_HINT (uint64_t * ; depuis Linux 4.13)
-
Définit la valeur de référence de lecture/écriture associée à la description
de fichier ouvert à laquelle se rapporte fd.
Si une description de fichier ouvert n'a pas de valeur de référence de
lecture/écriture assignée, elle devra utiliser la valeur affectée à l'inœud
s'il y en a une.
Les valeurs de référence de lecture/écriture suivantes sont applicables
depuis Linux 4.13 :
- RWH_WRITE_LIFE_NOT_SET
-
Aucune valeur de référence en particulier n'a été définie. Il s'agit de la
valeur par défaut.
- RWH_WRITE_LIFE_NONE
-
Aucune durée de vie spécifique à l'écriture n'a été associée à ce fichier ou
à cet inœud.
- RWH_WRITE_LIFE_SHORT
-
Les données écrites dans cet inœud ou via cette description de fichier
ouvert doivent avoir une durée de vie courte.
- RWH_WRITE_LIFE_MEDIUM
-
Les données écrites dans cet inœud ou via cette description de fichier
ouvert doivent avoir une durée de vie supérieure à celle des données écrites
avec RWH_WRITE_LIFE_SHORT.
- RWH_WRITE_LIFE_LONG
-
Les données écrites dans cet inœud ou via cette description de fichier
ouvert doivent avoir une durée de vie supérieure à celle des données écrites
avec RWH_WRITE_LIFE_MEDIUM.
- RWH_WRITE_LIFE_EXTREME
-
Les données écrites dans cet inœud ou via cette description de fichier
ouvert doivent avoir une durée de vie supérieure à celle des données écrites
avec RWH_WRITE_LIFE_LONG.
Toutes les valeurs de référence spécifiques à l'écriture sont relatives
entre elles et aucun sens absolu individuel ne devrait leur être attribué.
VALEUR RENVOYÉE
Pour qu'un appel réussisse, le code de retour dépend de l'opération :
- F_DUPFD
-
Le nouveau descripteur de fichier.
- F_GETFD
-
Valeur des attributs du descripteur de fichier.
- F_GETFL
-
Valeur des attributs d'état du fichier.
- F_GETLEASE
-
Le type de bail tenu sur le descripteur de fichier.
- F_GETOWN
-
Valeur du propriétaire du descripteur de fichier.
- F_GETSIG
-
La valeur du signal envoyé lorsque la lecture ou l'écriture deviennent
possibles, ou zéro pour le comportement SIGIO traditionnel.
- F_GETPIPE_SZ, F_SETPIPE_SZ
-
La capacité du tube.
- F_GET_SEALS
-
Un masque de bit identifiant les verrous positionnés sur le inœud auquel
renvoie fd.
- Toutes les autres commandes :
-
Zéro.
En cas d'erreur, la valeur de retour est -1 et errno est définie pour
préciser l'erreur.
ERREURS
- EACCES ou EAGAIN
-
L'opération est interdite en raison de verrous tenus par d'autres processus.
- EAGAIN
-
L'opération est impossible à cause d'une projection en mémoire effectuée par
un autre processus.
- EBADF
-
fd n'est pas un descripteur de fichier ouvert
- EBADF
-
fd vaut F_SETLK ou F_SETLKW et les droits d'ouverture sur le
descripteur de fichier ne correspondent pas au type de verrou demandé.
- EBUSY
-
cmd vaut F_SETPIPE_SZ et la capacité du nouveau tube indiqué dans
arg est inférieure à la taille de l'espace du tampon actuellement utilisé
pour stocker les données dans le tube.
- EBUSY
-
cmd vaut F_ADD_SEALS, arg inclut F_SEAL_WRITE et il existe un
tableau partagé accessible en écriture sur le fichier auquel se rapporte
fd.
- EDEADLK
-
Le verrouillage F_SETLKW conduirait à un interblocage.
- EFAULT
-
lock se trouve en dehors de l'espace d'adressage.
- EINTR
-
cmd vaut F_SETLKW ou F_OFD_SETLKW et l'opération a été interrompue
par un signal ; voir signal(7).
- EINTR
-
cmd vaut F_GETLK, F_SETLK, F_OFD_GETLK ou F_OFD_SETLK et
l'opération a été interrompue par un signal avant la vérification ou
l'acquisition du verrouillage. Généralement, quand on verrouille un fichier
distant (comme un verrou sur NFS), mais cela peut aussi arriver localement.
- EINVAL
-
La valeur indiquée dans cmd n'est pas reconnue par ce noyau.
- EINVAL
-
cmd vaut F_ADD_SEALS et arg inclut un bit de verrou non reconnu.
- EINVAL
-
cmd vaut F_ADD_SEALS ou F_GET_SEALS et le système de fichiers
contenant l'inœud auquel se rapporte fd ne prend pas en charge les
verrous.
- EINVAL
-
cmd vaut F_DUPFD et arg est négatif ou supérieur à la valeur
maximale permise (voir le point sur RLIMIT_NOFILE dans getrlimit(2)).
- EINVAL
-
cmd vaut F_SETSIG et arg n'est pas un numéro de signal autorisé.
- EINVAL
-
cmd est F_OFD_SETLK, F_OFD_SETLKW ou F_OFD_GETLK, et l_pid
n’a pas été défini comme nul.
- EMFILE
-
cmd vaut F_DUPFD et la limite par processus du nombre de descripteurs
de fichier ouverts a été atteinte.
- ENOLCK
-
Trop de verrous sont ouverts, ou la table des verrous est pleine, ou le
verrouillage distant (par exemple par NFS) a échoué.
- ENOTDIR
-
F_NOTIFY a été indiqué dans cmd, mais fd ne fait pas référence à un
répertoire.
- EPERM
-
cmd vaut F_SETPIPE_SZ et la limite rigide ou souple du tube de
l'utilisateur a été atteinte ; voir pipe(7).
- EPERM
-
Essai d'effacement de l'attribut O_APPEND sur un fichier, mais il est
considéré comme en-ajout-seulement.
- EPERM
-
cmd valait F_ADD_SEALS, mais fd n'était pas ouvert en écriture ou
le jeu de verrous actuel sur le fichier inclut déjà F_SEAL_SEAL.
STANDARDS
SVr4, 4.3BSD, POSIX.1-2001. 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-2001.
F_GETOWN et F_SETOWN sont spécifiées dans POSIX.1-2001 (pour activer
ces définitions, vous devez définir soit _XOPEN_SOURCE à la valeur
supérieure ou égale à 500, soit _POSIX_C_SOURCE à la valeur supérieure ou
égale à 200809L).
F_DUPFD_CLOEXEC est spécifiée dans POSIX.1-2008 (pour activer cette
définition, vous devez définir _POSIX_C_SOURCE avec une valeur supérieure
ou égale à 200809L, ou _XOPEN_SOURCE avec une valeur supérieure ou égale
à 700).
F_GETOWN_EX, F_SETOWN_EX, F_SETPIPE_SZ, F_GETPIPE_SZ,
F_GETSIG, F_SETSIG, F_NOTIFY, F_GETLEASE et F_SETLEASE sont
spécifiques à Linux. (Définissez la macro _GNU_SOURCE pour avoir ces
définitions).
F_OFD_SETLK, F_OFD_SETLKW et F_OFD_GETLK sont spécifiques à Linux
(et il faut définir _GNU_SOURCE pour obtenir leurs définitions), mais le
travail est en cours pour les avoir dans la prochaine version de POSIX.1.
F_ADD_SEALS et F_GET_SEALS sont spécifiques à Linux.
NOTES
Les erreurs renvoyées par dup2(2) ne sont pas les mêmes que celles
renvoyées par F_DUPFD.
Verrouillages de fichier
L'appel système fcntl() originel de Linux n'a pas été conçu pour gérer
les positions (dans la structure flock) dans des fichiers de très grosse
taille. En conséquence, Linux 2.4 a ajouté l'appel système fcntl64(). Ce
nouvel appel système utilise une structure différente de verrouillage de
fichier, flock64, ainsi que les commandes correspondantes F_GETLK64,
F_SETLK64 et F_SETLKW64. Cependant, ces détails peuvent être ignorés
par les applications qui utilisent la glibc, car sa fonction fcntl()
encapsule de manière transparente l'appel système le plus récent disponible.
Verrouillages d’enregistrements
Depuis Linux 2.0, il n'y a pas d'interaction entre les types de verrous
placés par flock(2) et fcntl().
Plusieurs systèmes ont d'autres champs dans struct flock comme, par
exemple, l_sysid (pour identifier la machine où se trouve le
verrou). Clairement, l_pid seul ne sera pas très utile si le processus
détenant le verrou s'exécute sur une autre machine ; sur Linux, bien que ce
champ soit présent sur certaines architectures (comme MIPS32), ce champ
n'est pas utilisé.
L'appel système fcntl() originel de Linux n'a pas été conçu pour gérer
les positions (dans la structure flock) dans des fichiers de très grosse
taille. En conséquence, Linux 2.4 a ajouté l'appel système fcntl64(). Ce
nouvel appel système utilise une structure différente de verrouillage de
fichier, flock64, ainsi que les commandes correspondantes F_GETLK64,
F_SETLK64 et F_SETLKW64. Cependant, ces détails peuvent être ignorés
par les applications qui utilisent la glibc, car sa fonction fcntl()
encapsule de manière transparente l'appel système le plus récent disponible.
Verrouillages d’enregistrements et NFS
Avant Linux 3.12, si un client NFSv4 perd le contact avec le serveur pendant
un certain temps (défini à plus de 90 secondes sans communication), il
pourrait perdre puis obtenir un nouveau verrou sans même en être
informé. (La période au bout de laquelle le contact est assumé perdu est
connue sous le nom de période de bail (« leasetime ») NFSv4. Sur un serveur
NFS Linux, elle peut être déterminée en regardant
/proc/fs/nfsd/nfsv4leasetime, qui exprime la période en seconde. La
valeur par défaut pour ce fichier est 90.) Ce scénario a pour risque
potentiel la corruption de données, puisqu’un autre processus pourrait
obtenir un verrou pendant la période intermédiaire et réaliser des entrées
et sorties de fichier.
Depuis Linux 3.12, si un client NFSv4 perd le contact avec le serveur,
toutes les entrées et sorties du fichier par un processus qui « pense »
détenir un verrou échoueront avant que le processus ne ferme et rouvre le
fichier. Un paramètre du noyau, nfs.recover_lost_locks, peut être défini
à 1 pour obtenir le comportement précédant (avant Linux 3.12), où le
client essayera de récupérer les verrous perdus quand le contact avec le
serveur est rétabli. À cause du risque associé de corruption de données, la
valeur par défaut de ce paramètre est 0 (désactivé).
BOGUES
F_SETFL
Il n'est pas possible d'utiliser F_SETFL pour modifier l'état des
attributs O_DSYNC et O_SYNC. Une tentative de modification de ces
attributs sera simplement ignorée.
F_GETOWN
En raison d'une limitation des conventions d'appels système sur certaines
architectures (en particulier i386), si F_GETOWN renvoie un identifiant
de groupe de processus compris entre -1 et -4095, la valeur de retour est
interprétée par glibc comme une erreur ; la valeur de retour de fcntl()
sera -1 et errno contiendra l'identifiant du groupe de processus
(positif). L’opération spécifique à Linux F_SETOWN_EX évite ce
problème. Depuis la glibc 2.11, glibc rend le problème avec F_GETOWN
invisible en implémentant F_GETOWN par-dessus F_GETOWN_EX.
F_SETOWN
Sous Linux 2.4 et précédents, lorsqu'un processus non privilégié utilise
F_SETOWN pour indiquer le propriétaire d'un socket, avec un identifiant
de (groupe de) processus autre que celui de l'appelant, un bogue peut
survenir. Dans ce cas, fcntl() peut renvoyer -1, avec errno
positionné à EPERM, même si l'appelant a le droit d'envoyer un signal à
ce (groupe de) processus. En dépit de cette erreur, le propriétaire du
descripteur de fichier est positionné, et les signaux seront envoyés au
propriétaire.
Détection d’interblocage
L’algorithme de détection d’interblocage utilisé par le noyau lors du
traitement de demandes F_SETLKW peut produire à la fois des faux négatifs
(échec de détection d’interblocages, laissant un ensemble de processus
interbloqués se bloquer indéfiniment) et des faux positifs (erreurs
EDEADLK alors qu’aucun interblocage n’existe). Par exemple, le noyau
limite la profondeur de verrouillage lors de sa recherche de dépendances à
dix étapes, ce qui signifie que les chaînes d’interblocages circulaires
dépassant cette taille ne seront pas détectées. De plus, le noyau pourrait
faussement indiquer un interblocage lorsqu’au moins deux processus créés en
utilisant l’attribut CLONE_FILES de clone(2) placent des verrous qui
semblent (au noyau) en conflit.
Verrouillage impératif
L'implémentation Linux du verrouillage impératif est sujette à des
conditions de concurrence qui la rende non fiable : un appel à write(2)
qui chevauche un verrou peut modifier les données après que le verrouillage
impératif a été acquis ; un appel à read(2) qui chevauche un verrou peut
détecter des modifications sur des données qui ont été faites seulement
après qu'un verrou en écriture a été acquis. Des conditions de concurrence
similaires existent entre les verrous impératifs et mmap(2). Il est donc
déconseillé de faire confiance au verrouillage impératif.
VOIR AUSSI
dup2(2), flock(2), open(2), socket(2), lockf(3),
capabilities(7), feature_test_macros(7), lslocks(8)
locks.txt, mandatory-locking.txt et dnotify.txt dans le répertoire
Documentation/filesystems/ des sources du noyau Linux. (Sur d'anciens
noyaux, ces fichiers se trouvent dans le répertoire Documentation/ et
mandatory-locking.txt est appelé mandatory.txt.)
TRADUCTION
La traduction française de cette page de manuel a été créée par
Christophe Blaess <https://www.blaess.fr/christophe/>,
Stéphan Rafin <stephan.rafin@laposte.net>,
Thierry Vignaud <tvignaud@mandriva.com>,
François Micaux,
Alain Portal <aportal@univ-montp2.fr>,
Jean-Philippe Guérard <fevrier@tigreraye.org>,
Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>,
Julien Cristau <jcristau@debian.org>,
Thomas Huriaux <thomas.huriaux@gmail.com>,
Nicolas François <nicolas.francois@centraliens.net>,
Florentin Duneau <fduneau@gmail.com>,
Simon Paillard <simon.paillard@resel.enst-bretagne.fr>,
Denis Barbier <barbier@debian.org>,
David Prévot <david@tilapin.org>
et
Jean-Philippe MENGUAL <jpmengual@debian.org>
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 à
Index
- NOM
-
- BIBLIOTHÈQUE
-
- SYNOPSIS
-
- DESCRIPTION
-
- Dupliquer un descripteur de fichier
-
- Attributs du descripteur de fichier
-
- Attribut d'état du fichier
-
- Verrouillages d’enregistrements coopératifs
-
- Verrouillages de description de fichier ouvert (non POSIX)
-
- Verrouillage impératif
-
- Verrouillages perdus
-
- Gestion des signaux
-
- Baux
-
- Notification de modification de fichier et de répertoire (dnotify)
-
- Changer la capacité d'un tube
-
- Verrouillages de fichier
-
- Indications de lecture/écriture de fichiers
-
- VALEUR RENVOYÉE
-
- ERREURS
-
- STANDARDS
-
- NOTES
-
- Verrouillages de fichier
-
- Verrouillages d’enregistrements
-
- Verrouillages d’enregistrements et NFS
-
- BOGUES
-
- F_SETFL
-
- F_GETOWN
-
- F_SETOWN
-
- Détection d’interblocage
-
- Verrouillage impératif
-
- VOIR AUSSI
-
- TRADUCTION
-
This document was created by
man2html,
using the manual pages.
Time: 05:05:17 GMT, May 18, 2024