Provided by: manpages-fr_3.65d1p1-1_all 

NOM
vDSO - Panorama de l’objet partagé dynamique ELF virtuel
SYNOPSIS
#include <sys/auxv.h>
void *vdso = (uintptr_t) getauxval(AT_SYSINFO_EHDR);
DESCRIPTION
Le « vDSO » (objet partagé dynamique virtuel, « virtual dynamic shared object ») est une petite
bibliothèque partagée que le noyau projette automatiquement dans l’espace d’adresses de toutes les
applications en espace utilisateur. Les applications n’ont normalement pas besoin de s’occuper
elles-mêmes de ces détails puisque le vDSO est d’habitude appelée par la bibliothèque C. Ainsi, vous
pouvez écrire du code normalement en utilisant les fonctions standards et la bibliothèque C s’occupera
d’utiliser toutes les fonctionnalités disponibles par l’intermédiaire du vDSO.
Pourquoi le vDSO existe ? Certains appels système fournis par le noyau finissent par être utilisés
fréquemment par le code en espace utilisateur, au point que ces appels peuvent avoir une emprise
excessive sur les performances. C’est à la fois dû à la fréquence des appels qu’aux nombreux changements
de contexte à force de sortir de l’espace utilisateur pour entrer dans le noyau.
La suite de cette documentation est orientée pour les curieux et les auteurs de la bibliothèque C plutôt
que pour les développeurs généraux. Si vous essayez d’appeler la vDSO dans vos propres applications
plutôt que d’utiliser la bibliothèque C, vous faites sans doute fausse route.
Contexte exemple
Réaliser des appels système peut être lent. Dans les systèmes 32 bits x86, vous pouvez déclencher une
interruption logicielle (int $0x80) pour indiquer au noyau que vous voulez faire un appel système.
Cependant, cette instruction est coûteuse : elle passe par tous les chemins complets de traitement des
interruptions dans le microcode du processeur ainsi que dans le noyau. Les nouveaux processeurs ont des
instructions plus rapides (mais non rétrocompatibles) pour initier les appels système. Plutôt que forcer
la bibliothèque C à vérifier si cette fonctionnalité est disponible au moment de l’exécution, la
bibliothèque C peut utiliser les fonctions fournies par le noyau dans le vDSO.
Remarquez que cette terminologie peut être source de confusion. Sur les systèmes x86, la fonction vDSO
utilisée pour déterminer la méthode préférée pour réaliser un appel système est appelée
« __kernel_vsyscall » alors que sous x86_64, le terme « vsyscall » se réfère aussi à une façon obsolète
de demander au noyau l’heure ou le processeur sur lequel est l’appelant.
Un appel système fréquemment utilisé est gettimeofday(2). Cet appel système est appelé à la fois
directement par les applications en espace utilisateur et indirectement par la bibliothèque C. Remarquez
que les horodatages, boucles temporelles ou scrutations — qui ont tous fréquemment besoin de savoir
l’heure exacte. Ce n’est pas non plus un secret — de n’importe quelle application dans n’importe quel
mode (superutilisateur ou utilisateur normal) auront tous la même réponse. Alors le noyau s’arrange pour
que les informations nécessaires pour répondre à cette question soient placées dans la mémoire accessible
au processus. Ainsi un appel de gettimeofday(2) est transformé d’un appel système en un appel normal de
fonction, avec un peu d’accès mémoire.
Trouver le vDSO
L’adresse de base du vDSO (s’il existe) est passée par le noyau à tous les programmes dans le vecteur
auxiliaire initial (consultez getauxval(3)) à l’aide du type AT_SYSINFO_EHDR.
Vous ne devez pas supposer que le vDSO est projeté à un endroit particulier de la projection en mémoire
de l’utilisateur. L’adresse de base sera normalement aléatoire au moment de l’exécution à chaque fois
qu’une nouvelle image de processus est créée (au moment de execve(2)). C’est ainsi pour des raisons de
sécurité, afin d’éviter les attaques de « retour vers libc ».
Pour certaines architectures, un type AT_SYSINFO est aussi présent. Il n’est utilisé que pour localiser
le point d’entrée vsyscall et est souvent omis ou défini à 0 (signifiant qu’il n’est pas disponible). Ce
type est un rappel du fonctionnement initial de vDSO (consultez Historique ci-dessous) et son utilisation
devrait être évitée.
Format de fichier
Puisque le vDSO est une image ELF complète, vous pouvez y rechercher des symboles. Cela permet d’ajouter
de nouveaux symboles avec les versions de noyau plus récentes et permet à la bibliothèque C de détecter
les fonctionnalités disponibles au moment de l’exécution lors de l’exécution sous différentes versions de
noyau. D’habitude, la bibliothèque C fera la détection lors du premier appel puis mettra en cache le
résultat pour les appels suivants.
Tous les appels sont aussi versionnés (en utilisant le format de version GNU). Cela permet au noyau de
mettre à jour la signature de fonction sans casser la rétrocompatibilité. Cela signifie modifier les
arguments acceptés par la fonction et la valeur de retour. Ainsi, lors de la recherche de symboles dans
le vDSO, vous devez toujours inclure la version pour correspondre à l’ABI attendue.
Typiquement, la vDSO suit la convention de nommage de préfixer tous les symboles par « __vdso_ » ou
« __kernel_ » afin de les distinguer des autres symboles standards. Par exemple, la fonction
« gettimeofday » est nommée « __vdso_gettimeofday ».
Utilisez les conventions d’appel C standard pour appeler n’importe laquelle de ces fonctions. Pas la
peine de vous embêter avec les registres bizarres ou les comportements de pile.
NOTES
Source
Lors de la compilation du noyau, le code vDSO est compilé et lié automatiquement. Il se trouve souvent
dans le répertoire spécifique à l’architecture :
find arch/$ARCH/ -name '*vdso*.so*' -o -name '*gate*.so*'
Noms vDSO
Le nom du vDSO dépend des architectures. Il est souvent visible dans des endroits comme la sortie de
ldd(1) de la glibc. Le nom exact ne devrait affecter aucun code, donc pas la peine de le coder en dur.
ABI utilisateur nom vDSO
────────────────────────────────────
aarch64 linux-vdso.so.1
ia64 linux-gate.so.1
ppc/32 linux-vdso32.so.1
ppc/64 linux-vdso64.so.1
s390 linux-vdso32.so.1
s390x linux-vdso64.so.1
sh linux-gate.so.1
i386 linux-gate.so.1
x86_64 linux-vdso.so.1
x86/x32 linux-vdso.so.1
NOTES SPÉCIFIQUES AUX ARCHITECTURES
Les sous-sections suivantes fournissent des notes spécifiques aux architectures sur le vDSO.
Remarquez que le vDSO utilisé est basé sur l’ABI du code en espace utilisateur et non sur l’ABI du noyau.
Ainsi, par exemple, si vous exécutez un binaire ELF 32 bits i386, vous obtiendrez le même vDSO que vous
l’exécutiez avec un noyau 32 bits i386 ou avec un noyau 64 bits x86_64. Par conséquent, le nom de l’ABI
en espace utilisateur devrait être utilisé pour déterminer la section suivante adéquate.
Fonctions ARM
Le portage ARM a une page de code pleine de fonctions utilitaires. Puisque ce n’est qu’une page de code
brut, aucune information ELF n’existe pour faire de la recherche de symboles ou du versionnement. Elle
fournit cependant une prise en charge pour plusieurs versions.
Pour des renseignements sur cette page de code, mieux vaut consulter la documentation du noyau
puisqu’elle est extrêmement détaillée et couvre tous ce que vous devez savoir :
Documentation/arm/kernel_user_helpers.txt.
Fonctions aarch64
Le tableau suivant indique les symboles exportés par le vDSO.
symbole version
──────────────────────────────────────
__kernel_rt_sigreturn LINUX_2.6.39
__kernel_gettimeofday LINUX_2.6.39
__kernel_clock_gettime LINUX_2.6.39
__kernel_clock_getres LINUX_2.6.39
Fonctions bfin (Blackfin)
Comme ce processeur n’a pas d’unité de gestion mémoire (MMU), il ne définit pas de vDSO au sens usuel. À
la place, il projette au démarrage quelques fonctions brutes à un endroit spécifique de la mémoire. Les
applications en espace utilisateur appellent ensuite directement dans cette zone. Aucune mesure de
rétrocompatibilité n’est prise à part en sniffant les codes opératoires bruts, mais comme il s’agit d’un
processeur embarqué, il peut s’en sortir impunément – certains formats d’objet qu’il exécute ne sont même
pas basés sur ELF (ils sont bFLT/FLAT).
Pour des renseignements sur cette page de code, mieux vaut consulter la documentation publique :
http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:fixed-code
Fonctions ia64 (Itanium)
Le tableau suivant indique les symboles exportés par le vDSO.
symbole version
───────────────────────────────────────
__kernel_sigtramp LINUX_2.5
__kernel_syscall_via_break LINUX_2.5
__kernel_syscall_via_epc LINUX_2.5
Le portage Itanium est un peu périlleux. En plus du vDSO ci-dessus, il a aussi des « appels système
légers » (aussi appelés « appels système rapides » ou « fsys »). Ils peuvent être appelés en à l’aide de
l’assistant vDSO __kernel_syscall_via_epc. Les appels système indiqués ici ont la même sémantique que si
vous les appeliez directement à l’aide de syscall(2), donc consultez la documentation adéquate pour
chacun d’entre eux. Le tableau suivant indique les fonctions disponibles par ce mécanisme.
fonction
────────────────
clock_gettime
getcpu
getpid
getppid
gettimeofday
set_tid_address
Fonctions parisc (hppa)
Le portage parisc à une page de code pleine de fonctions utilitaires appelée une page passerelle. Plutôt
que d’utiliser l’approche classique du vecteur auxiliaire ELF, il passe l’adresse de la page au processus
à l’aide du registre SR2. Les permissions sur la page sont telles qu’exécuter simplement ces adresses
s’exécute automatiquement avec les droits du noyau et pas en espace utilisateur. C’est ainsi afin de
correspondre au mode de fonctionnement HP-UX.
Puisque ce n’est qu’une page de code brut, aucune information ELF n’existe pour faire de la recherche de
symboles ou du versionnement. Appelez simplement l’adresse adéquate à l’aide de l’instruction de branche,
par exemple :
ble <adresse>(%sr2, %r0)
adresse fonction
────────────────────────────────────────
00b0 lws_entry
00e0 set_thread_pointer
0100 linux_gateway_entry (syscall)
0268 syscall_nosys
0274 tracesys
0324 tracesys_next
0368 tracesys_exit
03a0 tracesys_sigexit
03b8 lws_start
03dc lws_exit_nosys
03e0 lws_exit
03e4 lws_compare_and_swap64
03e8 lws_compare_and_swap
0404 cas_wouldblock
0410 cas_action
Fonctions ppc/32
Le tableau suivant indique les symboles exportés par le vDSO. Les fonctions marquées avec un * ne sont
disponibles que si le noyau est PowerPC64 (64 bits).
symbole version
────────────────────────────────────────
__kernel_clock_getres LINUX_2.6.15
__kernel_clock_gettime LINUX_2.6.15
__kernel_datapage_offset LINUX_2.6.15
__kernel_get_syscall_map LINUX_2.6.15
__kernel_get_tbfreq LINUX_2.6.15
__kernel_getcpu * LINUX_2.6.15
__kernel_gettimeofday LINUX_2.6.15
__kernel_sigtramp_rt32 LINUX_2.6.15
__kernel_sigtramp32 LINUX_2.6.15
__kernel_sync_dicache LINUX_2.6.15
__kernel_sync_dicache_p5 LINUX_2.6.15
Fonctions ppc/64
Le tableau suivant indique les symboles exportés par le vDSO.
symbole version
────────────────────────────────────────
__kernel_clock_getres LINUX_2.6.15
__kernel_clock_gettime LINUX_2.6.15
__kernel_datapage_offset LINUX_2.6.15
__kernel_get_syscall_map LINUX_2.6.15
__kernel_get_tbfreq LINUX_2.6.15
__kernel_getcpu LINUX_2.6.15
__kernel_gettimeofday LINUX_2.6.15
__kernel_sigtramp_rt64 LINUX_2.6.15
__kernel_sync_dicache LINUX_2.6.15
__kernel_sync_dicache_p5 LINUX_2.6.15
Fonctions s390
Le tableau suivant indique les symboles exportés par le vDSO.
symbole version
──────────────────────────────────────
__kernel_clock_getres LINUX_2.6.29
__kernel_clock_gettime LINUX_2.6.29
__kernel_gettimeofday LINUX_2.6.29
Fonctions s390x
Le tableau suivant indique les symboles exportés par le vDSO.
symbole version
──────────────────────────────────────
__kernel_clock_getres LINUX_2.6.29
__kernel_clock_gettime LINUX_2.6.29
__kernel_gettimeofday LINUX_2.6.29
Fonctions sh (SuperH)
Le tableau suivant indique les symboles exportés par le vDSO.
symbole version
──────────────────────────────────
__kernel_rt_sigreturn LINUX_2.6
__kernel_sigreturn LINUX_2.6
__kernel_vsyscall LINUX_2.6
Fonctions i386
Le tableau suivant indique les symboles exportés par le vDSO.
symbole version
──────────────────────────────────
__kernel_sigreturn LINUX_2.5
__kernel_rt_sigreturn LINUX_2.5
__kernel_vsyscall LINUX_2.5
Fonctions x86_64
Le tableau suivant indique les symboles exportés par le vDSO. Tous ces symboles sont aussi disponibles
sans le préfixe « __vdso_ », mais vous devriez les ignorer et vous cantonner aux noms suivants.
symbole version
─────────────────────────────────
__vdso_clock_gettime LINUX_2.6
__vdso_getcpu LINUX_2.6
__vdso_gettimeofday LINUX_2.6
__vdso_time LINUX_2.6
Fonctions x86/x32
Le tableau suivant indique les symboles exportés par le vDSO.
symbole version
─────────────────────────────────
__vdso_clock_gettime LINUX_2.6
__vdso_getcpu LINUX_2.6
__vdso_gettimeofday LINUX_2.6
__vdso_time LINUX_2.6
Historique
Le vDSO n’était à l’origine qu’une seule fonction — le vsyscall. Dans les anciens noyaux, ce nom pourrait
être vu dans une projection en mémoire de processus à la place de « vdso ». Le temps passant, les gens
ont réalisé que ce mécanisme était un excellent moyen pour passer plus de fonctionnalités à l’espace
utilisateur, il a donc été reconçu en tant que vDSO au format actuel.
VOIR AUSSI
syscalls(2), getauxval(3), proc(5)
Les documents, exemples et le code source dans l’arborescence du code source de Linux :
Documentation/ABI/stable/vdso
Documentation/ia64/fsys.txt
Documentation/vDSO/* (contient des exemples d’utilisation du vDSO)
find arch/ -iname '*vdso*' -o -iname '*gate*'
COLOPHON
Cette page fait partie de la publication 3.65 du projet man-pages Linux. Une description du projet et des
instructions pour signaler des anomalies peuvent être trouvées à l'adresse
http://www.kernel.org/doc/man-pages/.
TRADUCTION
Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a <http://po4a.alioth.debian.org/> par
l'équipe de traduction francophone au sein du projet perkamon <http://perkamon.alioth.debian.org/>.
Veuillez signaler toute erreur de traduction en écrivant à <debian-l10n-french@lists.debian.org> ou par
un rapport de bogue sur le paquet manpages-fr.
Vous pouvez toujours avoir accès à la version anglaise de ce document en utilisant la commande « man -L C
<section> <page_de_man> ».
Linux 1er février 2014 VDSO(7)