futex – Verrouillage rapide en mode utilisateur
#include <linux/futex.h>
Le noyau Linux fournit des futex (« Fast user-space
mutexes ») en tant que brique permettant un verrouillage rapide
et des sémaphores en espace utilisateur. Les futex sont très
basiques et se prêtent facilement à la construction
d'abstractions de verrouillage de plus haut niveau telles que les mutex, les
conditions variables, les blocages en écriture/lecture, les
barrières et les sémaphores.
En fait, la plupart des programmeurs n’ont pas à utiliser les
futex directement ; ils s'appuient plutôt sur les
bibliothèques construites à partir d’eux, telle que NPTL
(Native POSIX Thread Library) (consultez
pthreads(7)).
Un futex est identifié par une zone mémoire qui peut être
partagée entre plusieurs processus ou plusieurs fils
d’exécution. Dans ces différents processus, il n'a pas
forcément la même adresse. Dans sa forme la plus simple, un
futex a la sémantique d'un sémaphore ; il s'agit d'un
compteur qui peut être incrémenté et
décrémenté de façon atomique. Les processus
peuvent attendre que cette valeur devienne positive.
Une opération sur un futex est faite entièrement en espace
utilisateur dans le cas où il n'y a pas de sous-capacité. Le
noyau n'est impliqué que pour arbitrer en cas de sous-capacité.
Comme toute conception saine évite cela, les futex sont aussi optimaux
pour cette situation.
Dans sa forme basique, un futex est un entier aligné qui n'est
modifié que par des instructions atomiques d’assembleur. Cet
entier se compose de quatre octets sur toutes les plateformes. Des processus
peuvent partager cet entier en utilisant
mmap(2), à
l’aide de segments de mémoire partagés, ou parce qu'ils
partagent leur espace mémoire, auquel cas l'application est dite
multithreadée.
Toute opération futex démarre en espace utilisateur, mais il peut
être nécessaire de communiquer avec le noyau en utilisant
l'appel système
futex(2).
Pour incrémenter un futex, exécuter les instructions assembleur
qui causent l'incrémentation de manière atomique de l'entier par
le processeur hôte. Ensuite, vérifier si sa valeur a
changé de 0 à 1, auquel cas il n'y avait pas de
processus en attente et l'opération est réalisée. Il
s'agit du cas sans sous-capacité, qui est rapide et devrait être
fréquent.
En cas de sous-capacité, l'incrémentation atomique a
modifié la valeur -1 (ou une autre valeur négative) du
compteur. Si cette situation est détectée, il y a des processus
en attente. L'espace utilisateur doit alors définir le compteur
à 1 et demander au noyau de réveiller les processus en
attente avec l'opération
FUTEX_WAKE.
Attendre sur un futex, pour décrémenter le compteur, est
l'opération inverse. Décrémenter le compteur de
façon atomique et vérifier si sa nouvelle valeur est 0,
auquel cas l'opération est réalisée et le futex
n’était pas dans un cas de sous-capacité. Dans tous les
autres cas, le processus doit régler le compteur à -1 et
demander à ce que le noyau attende qu'un autre processus
incrémente le futex. Pour cela, utiliser l'opération
FUTEX_WAIT.
Un délai peut éventuellement être passé en argument
à l'appel système
futex(2), qui indique combien de temps
le noyau doit attendre que le futex soit incrémenté. Dans ce
cas, la sémantique est plus complexe et le programmeur devrait lire
futex(2) pour plus de détails. La même remarque est
valable pour l'attente asynchrone sur un futex.
La gestion des futex a été intégrée à
Linux 2.5.7, mais avec une sémantique différente de celle
décrite ci-dessus. La sémantique actuelle est disponible depuis
Linux 2.5.40.
Pour rappel, les futex de base ne sont pas conçus comme une abstraction
facile à employer pour les utilisateurs finaux. Les personnes les
mettant en pratique doivent maîtriser l'assembleur et avoir lu les
sources de la bibliothèque futex en espace utilisateur décrite
ci-dessous.
Cette page de manuel illustre l'utilisation la plus courante des primitives
futex(2). Il ne s'agit absolument pas de la seule.
clone(2),
futex(2),
get_robust_list(2),
set_robust_list(2),
set_tid_address(2),
pthreads(7)
Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux (proceedings
of the Ottawa Linux Symposium 2002), futex example library, futex-*.tar.bz2
https://mirrors.kernel.org/pub/linux/kernel/people/rusty/
La traduction française de cette page de manuel a été
créée par Christophe Blaess
<
https://www.blaess.fr/christophe/>, Stéphan Rafin
<
[email protected]>, Thierry Vignaud
<
[email protected]>, François Micaux, Alain Portal
<
[email protected]>, Jean-Philippe Guérard
<
[email protected]>, Jean-Luc Coulon (f5ibh)
<
[email protected]>, Julien Cristau
<
[email protected]>, Thomas Huriaux <
[email protected]>,
Nicolas François <
[email protected]>, Florentin
Duneau <
[email protected]>, Simon Paillard
<
[email protected]>, Denis Barbier
<
[email protected]>, David Prévot <
[email protected]> et
Jean-Paul Guillonneau <
[email protected]>
Cette traduction est une documentation libre ; veuillez vous reporter
à la
GNU
General Public License version 3 concernant les conditions de copie
et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel,
veuillez envoyer un message à
[email protected]