fcntl(2) | System Calls Manual | fcntl(2) |
fcntl - Manipuler un descripteur de fichier
Bibliothèque C standard (libc, -lc)
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
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.
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).
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.
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).
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.
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.
Les verrouillages de description de fichier ouvert apportent une solution à ces deux problèmes.
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.
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).
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.
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.
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 :
struct f_owner_ex {
int type;
pid_t pid; };
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).
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.
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.
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.)
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.
Les verrous suivants sont disponibles :
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 :
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 :
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é.
Pour qu'un appel réussisse, le code de retour dépend de l'opération :
En cas d'erreur, la valeur de retour est -1 et errno est définie pour préciser l'erreur.
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.
Les erreurs renvoyées par dup2(2) ne sont pas les mêmes que celles renvoyées par F_DUPFD.
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.
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.
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é).
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.
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.
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.
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.
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.
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.)
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 à debian-l10n-french@lists.debian.org.
5 février 2023 | Pages du manuel de Linux 6.03 |