1. Supports de cours
  2. Programmation système - Maîtrisez les appels système Linux avec le langage C (Nouvelle édition)

Programmation système Maîtrisez les appels système Linux avec le langage C (Nouvelle édition)

  • Accès illimité 24h/24, 7J/7
  • Tous les livres en ligne, les vidéos et les cours enregistrés ENI
  • Plus de 10 nouveautés livres et vidéos chaque mois
  • Les nouveautés disponibles le jour de leur sortie
  • Accès 100% en ligne
  • En stock
  • Expédié en 24h00
  • Livraison à partir de 0,01 €
  • Version en ligne offerte
  • 1 h d'accès gratuit à tous nos livres et vidéos pour chaque commande
  • Accessible immédiatement
  • Version HTML
  • Accès illimité 24h/24, 7J/7

Présentation

Avec ce livre, le lecteur dispose des connaissances nécessaires pour maîtriser la programmation avec les appels système Linux, en langage C, et développer des applications s'interfaçant directement avec le noyau afin d'exploiter au maximum ses fonctionnalités. L'auteur s'appuie sur les versions récentes du noyau Linux et sur les implémentations modernes des appels système. Il s'adresse principalement à un public de programmeurs pratiquant le langage C et ayant déjà l'expérience d'une distribution GNU/Linux ou d'un système de type Unix.

Après une description générale des appels système Linux (principes, normes, documentation…), l'auteur présente leurs principaux domaines d'utilisation. Il détaille la gestion des fichiers et des répertoires puis celle des processus avant d'étudier les mécanismes de communication et de synchronisation issus du monde Unix classique : les tubes (anonymes et nommés) et les signaux. L'auteur décrit ensuite les deux ensembles de mécanismes de communication inter processus (IPC) implémentés par le noyau Linux, ceux d'origine Unix SYSTEM V et ceux, plus récents, définis dans le cadre des normes POSIX, permettant de gérer la mémoire partagée, les files d'attente de messages et les sémaphores. Il expose les techniques de communication réseau via les sockets, en mode connecté et en mode datagramme, et conclut le livre avec la gestion des threads POSIX.

Pour faciliter la compréhension et l'acquisition réelle des différents mécanismes, l'auteur présente les concepts fondamentaux et les illustre par de nombreux programmes d'exemple en langage C, courts et faciles à appréhender, téléchargeables sur le site sur le site www.editions-eni.fr.



Quizinclus dans
la version en ligne !
  • Testez vos connaissances à l'issue de chaque chapitre
  • Validez vos acquis

Table des matières

  • Introduction aux appels système Linux
    • 1. Notion d'appel système
      • 1.1 Rôle du noyau
      • 1.2 Appel système
        • 1.2.1 Exécution d'un appel système
        • 1.2.2 Mode utilisateur et mode noyau
      • 1.3 Utilisation des appels système en langage C
        • 1.3.1 Fonctions enveloppes (wrappers)
        • 1.3.2 La fonction syscall()
        • 1.3.3 Fonctions de haut niveau
    • 2. Normes et standards
      • 2.1 POSIX (Portable Operating System Interface X)
      • 2.2 SUS (Single Unix Specification)
      • 2.3 Linux et les normes
    • 3. Documentation
    • 4. Portabilité et types
    • 5. Gestion des erreurs
      • 5.1 Code retour et variable errno
      • 5.2 Fonctions de gestion des erreurs
    • 6. Un premier programme système
      • 6.1 Documentation de l'appel système
      • 6.2 Programme source
      • 6.3 Compilation et exécution
  • Les fichiers
    • 1. Principes généraux
      • 1.1 L’interface fichier universelle
      • 1.2 Système de fichiers
      • 1.3 Chemin d'accès d'un fichier
        • 1.3.1 Chemin d'accès absolu ou relatif
        • 1.3.2 Répertoire courant, répertoire parent
        • 1.3.3 Analyse d'un chemin d'accès
      • 1.4 Types de fichiers
        • 1.4.1 Fichiers ordinaires (regular files)
        • 1.4.2 Répertoires
        • 1.4.3 Fichiers spéciaux
        • 1.4.4 Liens symboliques
        • 1.4.5 Tubes nommés et sockets
      • 1.5 Gestion des fichiers ouverts
        • 1.5.1 Descripteur de fichier
        • 1.5.2 Table des fichiers ouverts par le processus
        • 1.5.3 Table des fichiers ouverts sur le système
        • 1.5.4 Table des inodes ouverts
      • 1.6 Entrées/sorties standards
    • 2. Ouverture/fermeture d'un fichier
      • 2.1 Appel système open()
      • 2.2 Modes d’ouverture
      • 2.3 Options d’ouverture
      • 2.4 Exemples d’ouvertures de fichiers existants
        • 2.4.1 Lecture
        • 2.4.2 Écriture
        • 2.4.3 Écriture avec remise à zéro
        • 2.4.4 Lecture, sauf lien symbolique
        • 2.4.5 Lecture avec remise à zéro
      • 2.5 Création d’un fichier
        • 2.5.1 Argument Permissions
        • 2.5.2 Gestion de l’umask
        • 2.5.3 Exemples de création d’un fichier
      • 2.6 Erreurs
      • 2.7 Fermeture d’un fichier
    • 3. Lecture d’un fichier
    • 4. Écriture d’un fichier
    • 5. Déplacement dans un fichier
    • 6. Gestion des fichiers ouverts
      • 6.1 Obtenir les options d’ouverture
        • 6.1.1 Exemple
      • 6.2 Modifier les options d’ouverture
    • 7. Duplication de descripteurs
      • 7.1 Appel système dup()
      • 7.2 Appel système dup2()
    • 8. Gestion des répertoires et des liens
      • 8.1 Notion de lien physique
      • 8.2 Répertoires et liens physiques
      • 8.3 Processus et répertoires
      • 8.4 Liens symboliques
      • 8.5 Gestion des liens physiques
        • 8.5.1 Appel système link()
        • 8.5.2 Appel système unlink()
      • 8.6 Changement de nom ou déplacement
      • 8.7 Gestion des liens symboliques
        • 8.7.1 Création d’un lien symbolique : symlink()
        • 8.7.2 Lecture du chemin d’accès cible : readlink()
      • 8.8 Créer un répertoire : mkdir()
      • 8.9 Supprimer un répertoire : rmdir()
      • 8.10 Lister le contenu d'un répertoire
        • 8.10.1 Ouvrir un répertoire : opendir(), fdopendir()
        • 8.10.2 Parcourir la liste d'un répertoire : readdir()
        • 8.10.3 Repartir du début de la liste : rewinddir()
        • 8.10.4 Fermer la liste : closedir()
        • 8.10.5 Exemple de parcours d'un répertoire
      • 8.11 Gestion du répertoire courant
        • 8.11.1 Déterminer le répertoire courant : getcwd()
        • 8.11.2 Changer de répertoire courant : chdir(), fchdir()
        • 8.11.3 Exemple de changement de répertoire
      • 8.12 Changer le répertoire racine du processus : chroot()
    • 9. Lire les attributs d'un fichier
      • 9.1 Appels système stat(), lstat(), fstat()
      • 9.2 Appel système fstatat()
      • 9.3 Structure stat
      • 9.4 Exemple
    • 10. Gestion du contrôle d'accès
      • 10.1 Propriétaire et groupe d'un fichier
      • 10.2 Changement de propriétaire et de groupe
      • 10.3 Droits spéciaux d'un fichier
        • 10.3.1 setuserid bit
        • 10.3.2 setgroupid bit
        • 10.3.3 sticky bit
      • 10.4 Permissions d'accès d'un fichier
        • 10.4.1 Types d'accès pour un répertoire
        • 10.4.2 Détermination des droits d'accès
      • 10.5 Modifier les droits et permissions d'accès
      • 10.6 Exemple de contrôle d'accès
    • 11. Verrouillage d'un fichier
      • 11.1 Types de verrous
        • 11.1.1 Verrouillage consultatif ou impératif
        • 11.1.2 Verrouillage en lecture ou en écriture
      • 11.2 Gestion des verrous par fcntl()
        • 11.2.1 Structure flock
        • 11.2.2 Commandes de gestion de verrou
        • 11.2.3 Libération de verrou
        • 11.2.4 Étreinte fatale
        • 11.2.5 Limites
        • 11.2.6 Exemple de gestion de verrou
    • 12. Fichiers gérés en mémoire (mapping)
      • 12.1 Projection en mémoire : mmap()
      • 12.2 Forcer la mise à jour du fichier projeté : msync()
      • 12.3 Terminer une projection mémoire : munmap()
  • Les processus
    • 1. Processus et programme
      • 1.1 Programme exécutable
      • 1.2 Script
      • 1.3 Processus
      • 1.4 Zones mémoire d’un processus
    • 2. Attributs d’un processus
      • 2.1 Identifiant du processus (PID)
      • 2.2 Identifiant du parent du processus (PPID - Parent Process ID)
      • 2.3 Comptes utilisateur du processus (rUID, eUID)
        • 2.3.1 Identifiant utilisateur réel
        • 2.3.2 Identifiant utilisateur effectif
        • 2.3.3 Identifiant utilisateur setuid sauvegardé
        • 2.3.4 Identifiant utilisateur système de fichiers
      • 2.4 Processus privilégié
      • 2.5 Groupes utilisateurs du processus (GID, eGID)
        • 2.5.1 Identifiant groupe utilisateur réel
        • 2.5.2 Identifiant groupe utilisateur effectif
        • 2.5.3 Identifiant groupe utilisateur setgid sauvegardé
        • 2.5.4 Identifiant groupe utilisateur système de fichiers
        • 2.5.5 Groupes utilisateurs supplémentaires
      • 2.6 Répertoire courant du processus
      • 2.7 Répertoire racine du processus
      • 2.8 Valeur d'umask
      • 2.9 Sessions et groupes de processus
        • 2.9.1 Session de processus
        • 2.9.2 Groupe de processus
        • 2.9.3 Utilisation
      • 2.10 Le pseudosystème de fichiers proc
    • 3. Environnement d’un processus
      • 3.1 Lire l’environnement : getenv()
      • 3.2 Modifier l’environnement : setenv()
    • 4. Créer un processus : fork()
    • 5. Gestion des attributs d'un processus
      • 5.1 Identifiants de processus : getpid(), getppid()
      • 5.2 Identifiants de groupe et de session : getpgid(), getsid()
      • 5.3 Identifiants d’utilisateurs : getuid()
      • 5.4 Identifiants de groupes d’utilisateurs : getgid()
      • 5.5 Modification des identifiants : setuid(), setgid()
        • 5.5.1 Description de setuid()
        • 5.5.2 Description de seteuid()
        • 5.5.3 Description de setreuid()
        • 5.5.4 Description de setresuid()
        • 5.5.5 Gestion des identifiants de groupes utilisateurs
        • 5.5.6 Gestion des identifiants de systèmes de fichiers
      • 5.6 Exemples
    • 6. Terminaison d'un processus
      • 6.1 Appel système _exit()
      • 6.2 Appels indirects à _exit()
        • 6.2.1 La fonction exit()
        • 6.2.2 Terminaison de la fonction main()
      • 6.3 Exemple
    • 7. Relations entre processus parent et enfant
      • 7.1 Appel système wait()
      • 7.2 Le signal SIGCHLD
      • 7.3 Processus parent/enfant et fichiers
    • 8. Processus zombie
      • 8.1 Adoption d’un processus orphelin
      • 8.2 Exemple
    • 9. Chargement et exécution d'un programme externe
      • 9.1 Appel système execve()
      • 9.2 Exécution d’un script
      • 9.3 Gestion des fichiers ouverts
      • 9.4 La famille de fonctions exec()
      • 9.5 La fonction system()
  • Les signaux
    • 1. Les principes
      • 1.1 Qu'est-ce qu'un signal ?
      • 1.2 Gestion par défaut des signaux
        • 1.2.1 Signal SIGKILL
        • 1.2.2 Fichier de vidage mémoire (core dump)
      • 1.3 Modification de l'effet des signaux
      • 1.4 Émission d'un signal
      • 1.5 Réception d'un signal
    • 2. Les types de signaux
      • 2.1 Signaux d'origine utilisateur
        • 2.1.1 Signaux liés au clavier
        • 2.1.2 La commande kill
      • 2.2 Signaux émis à l'initiative du noyau
        • 2.2.1 Événements matériels
        • 2.2.2 Erreur du processus
        • 2.2.3 Événements liés aux processus
      • 2.3 Liste des signaux traditionnels Linux
    • 3. Envoi d'un signal
      • 3.1 Appel système kill()
      • 3.2 Exemples
    • 4. Traitement des signaux
      • 4.1 Appel système signal()
        • 4.1.1 Description d'un signal : psignal()
      • 4.2 Appel système sigaction()
      • 4.3 Bloquer un signal : sigprocmask()
        • 4.3.1 Liste des signaux pendants : sigpending()
        • 4.3.2 Exemple
      • 4.4 Principes d'un gestionnaire de signal
        • 4.4.1 Fonctions réentrantes
        • 4.4.2 Rôle d'un gestionnaire de signal
        • 4.4.3 Protéger les sections critiques
        • 4.4.4 Signaux applicatifs
      • 4.5 Attendre un signal quelconque : pause()
      • 4.6 Traitement du signal SIGCHLD
        • 4.6.1 Gestionnaire d'attente de terminaison processus enfant
        • 4.6.2 Exemple de gestionnaire SIGCHLD
        • 4.6.3 Autres méthodes de gestion de la terminaison des processus enfants
        • 4.6.4 Exemples
    • 5. Signaux et démons
      • 5.1 Principes d'initialisation d'un daemon System V
      • 5.2 Daemon géré par systemd
      • 5.3 Daemons et signaux
  • Les tubes et les tubes nommés
    • 1. Les principes
      • 1.1 Flot d'octets (bytestream)
      • 1.2 Lecture dans un tube
      • 1.3 Écriture dans un tube
      • 1.4 Gestion des tubes par le noyau
        • 1.4.1 Inode d'un tube
        • 1.4.2 Durée de vie d'un tube
    • 2. Les tubes anonymes (pipes)
      • 2.1 Création d'un tube
      • 2.2 Attributs d'un tube
        • 2.2.1 Lecture des informations de l'inode
        • 2.2.2 Mode d'ouverture d'un tube
        • 2.2.3 L'appel système pipe2()
        • 2.2.4 Taille maximale d'un tube
        • 2.2.5 Exemples
      • 2.3 Fermeture d'un tube
        • 2.3.1 Exemple
      • 2.4 Utilisation d'un tube entre plusieurs processus
        • 2.4.1 Tube sur la ligne de commande
        • 2.4.2 Tube entre processus parent et enfant
        • 2.4.3 Exemple
      • 2.5 Redirection et tube
        • 2.5.1 Principe
        • 2.5.2 Exemple
      • 2.6 Tube avec une ligne de commande shell
      • 2.7 Signaux et tubes
        • 2.7.1 Signal SIGPIPE
        • 2.7.2 Écriture interrompue
        • 2.7.3 Exemple
    • 3. Les tubes nommés
      • 3.1 Création d'un tube nommé
      • 3.2 Ouverture d'un tube nommé
        • 3.2.1 Ouverture non bloquante
        • 3.2.2 Exemple
      • 3.3 Utilisation d'un tube nommé
        • 3.3.1 Lecture
        • 3.3.2 Écriture
        • 3.3.3 Fermeture
        • 3.3.4 Attributs et options d'ouverture d'un tube nommé
        • 3.3.5 Suppression
      • 3.4 Exemple
  • Communication interprocessus (IPC)
    • 1. Principes de communication interprocessus
      • 1.1 IPC System V et IPC POSIX
      • 1.2 Fonctions des différents mécanismes d'IPC
        • 1.2.1 Segment de mémoire partagée
        • 1.2.2 Files d'attente de messages
        • 1.2.3 Sémaphores
    • 2. Les segments de mémoire partagée
      • 2.1 Les segments de mémoire partagée System V
        • 2.1.1 Création d'un segment de mémoire partagée : shmget()
        • 2.1.2 Identifiants d'un segment de mémoire partagée
        • 2.1.3 Générer une clef d'identification : ftok()
        • 2.1.4 Exemple de création d'un segment de mémoire partagée
        • 2.1.5 Informations sur un segment de mémoire partagée System V : ipcs
        • 2.1.6 Accès à un segment de mémoire partagée : shmat()
        • 2.1.7 Contrôle d'un segment de mémoire partagée : shmctl()
        • 2.1.8 Détachement d’un segment de mémoire partagée : shmdt()
      • 2.2 Les segments de mémoire partagée POSIX
        • 2.2.1 Création / ouverture d’un objet de mémoire partagée : shm_open()
        • 2.2.2 Utilisation de l’objet mémoire partagée : mmap()
        • 2.2.3 Contrôle d’un objet de mémoire partagée
        • 2.2.4 Suppression d’un objet de mémoire partagée : shm_unlink()
    • 3. Les files d'attente de messages
      • 3.1 Les files d’attente de messages System V
        • 3.1.1 Création d'une file d’attente de messages System V : msgget()
        • 3.1.2 Identifiants d'une file d’attente de messages System V
        • 3.1.3 Générer une clef d'identification : ftok()
        • 3.1.4 Exemple de création d'une file d’attente de messages System V
        • 3.1.5 Informations sur une file d’attente de messages System V : msgctl()
        • 3.1.6 Accès à une file d’attente de messages System V
        • 3.1.7 Envoi de messages : msgsnd()
        • 3.1.8 Lecture de messages : msgrcv()
        • 3.1.9 Contrôle d'une file d’attente de messages System V : msgctl()
      • 3.2 Les files d’attente de messages POSIX
        • 3.2.1 Ouverture ou création d'une file d’attente de messages POSIX : mq_open()
        • 3.2.2 Exemple de création d'une file d’attente de messages POSIX
        • 3.2.3 Informations sur une file d’attente de messages POSIX
        • 3.2.4 Envoi de messages : mq_send()
        • 3.2.5 Lecture de messages : mq_receive()
        • 3.2.6 Contrôle d'une file d’attente de messages POSIX : mq_setattr()
        • 3.2.7 Fermeture d'une file d’attente de messages POSIX : mq_close()
        • 3.2.8 Suppression d'une file d’attente de messages POSIX : mq_unlink()
        • 3.2.9 Lecture/écriture de messages avec time-out : mq_timedsend(), mq_timedreceive()
        • 3.2.10 Lecture de messages par notification : mq_notify()
    • 4. Les sémaphores
      • 4.1 Les sémaphores System V
        • 4.1.1 Créer un jeu de sémaphores System V : semget()
        • 4.1.2 Identifiants d'un jeu de sémaphores
        • 4.1.3 Générer une clef d'identification : ftok()
        • 4.1.4 Exemple de création d'un jeu de sémaphores
        • 4.1.5 Informations sur un jeu de sémaphores System V
        • 4.1.6 Contrôler et initialiser un jeu de sémaphores System V : semctl()
        • 4.1.7 Utiliser un jeu de sémaphores System V : semop()
      • 4.2 Les sémaphores POSIX
        • 4.2.1 Créer ou ouvrir un sémaphore POSIX : sem_open()
        • 4.2.2 Exemple de création d'un sémaphore POSIX
        • 4.2.3 Informations sur un sémaphore POSIX : sem_getvalue()
        • 4.2.4 Utiliser un sémaphore POSIX : sem_post(), sem_wait()
        • 4.2.5 Fermer un sémaphore POSIX : sem_close()
        • 4.2.6 Supprimer un sémaphore POSIX : sem_unlink()
        • 4.2.7 Les sémaphores POSIX anonymes : sem_init(), sem_destroy()
  • Communication réseau par les sockets
    • 1. Principes des sockets
      • 1.1 Rôle des sockets
      • 1.2 Types de sockets
        • 1.2.1 Stream
        • 1.2.2 Datagramme
      • 1.3 Domaines de communication
        • 1.3.1 Domaine IP version 4
        • 1.3.2 Domaine IP version 6
        • 1.3.3 Domaine Unix
    • 2. Gestion des adresses, numéros de port, noms d'hôtes et de services
      • 2.1 Représentation des adresses et des données
        • 2.1.1 Représentation des données
      • 2.2 Gestion des adresses de socket
        • 2.2.1 Structure générique sockaddr
        • 2.2.2 Structures de stockage des adresses sockets
        • 2.2.3 Conversion d'une adresse chaîne de caractères en numérique : inet_pton()
        • 2.2.4 Conversion d'une adresse numérique en chaîne de caractères : inet_ntop()
        • 2.2.5 Gestion des erreurs : gai_strerror()
      • 2.3 Gestion des relations noms et adresses
        • 2.3.1 Anciennes fonctions
        • 2.3.2 Recherche d'adresse et/ou de numéro de port : getaddrinfo()
        • 2.3.3 Recherche de nom d'hôte ou de service : getnameinfo()
    • 3. Sockets en mode stream
      • 3.1 Créer une socket : socket()
      • 3.2 Lier une socket à une adresse : bind()
      • 3.3 Écouter une socket : listen()
      • 3.4 Attente de connexion : accept()
      • 3.5 Demande de connexion : connect()
      • 3.6 Informations sur une socket : getsockname(), getpeername()
      • 3.7 Fermer une connexion close(), shutdown()
        • 3.7.1 close()
        • 3.7.2 shutdown()
      • 3.8 Utilisation d'une connexion socket : appels système fichiers
        • 3.8.1 Utilisation avec read(), write()
        • 3.8.2 Serveur monoprocessus
        • 3.8.3 Serveur multiprocessus
      • 3.9 Utilisation d'une connexion socket : appels système spécifiques
        • 3.9.1 Réception : recv()
        • 3.9.2 Émission : send()
        • 3.9.3 Envoi d'un fichier : sendfile ()
        • 3.9.4 Exemple client-serveur send()/recv()/sendfile()
    • 4. Sockets en mode datagramme
      • 4.1 Créer une socket datagramme : socket()
      • 4.2 Lier une socket datagramme à une adresse : bind()
      • 4.3 Utilisation de connect() en mode datagramme
      • 4.4 Utiliser une socket datagramme
        • 4.4.1 Émission d'un datagramme : sendto()
        • 4.4.2 Réception d'un datagramme : recvfrom()
        • 4.4.3 Envoi de datagramme en broadcast
      • 4.5 Exemple de communication par datagrammes
  • Les threads
    • 1. Principes des threads
      • 1.1 Threads POSIX
      • 1.2 Threads Linux
    • 2. Threads et processus
      • 2.1 Threads et appels système de niveau processus
        • 2.1.1 Appel système execve() en contexte multithreads
        • 2.1.2 Appel système fork() en contexte multithreads
        • 2.1.3 Appel système exit() en contexte multithreads
        • 2.1.4 Threads et signaux
      • 2.2 Multiprocessus ou multithreads ?
        • 2.2.1 Avantages du multithreads
        • 2.2.2 Avantages du multiprocessus
    • 3. Gestion des threads
      • 3.1 Création d'un thread : pthread_create()
        • 3.1.1 pthread_create()
        • 3.1.2 Identifiant d'un thread : pthread_self()
      • 3.2 Terminaison d'un thread : pthread_exit()
        • 3.2.1 pthread_exit()
        • 3.2.2 Thread zombie
      • 3.3 Attendre la terminaison d'un thread : pthread_join()
      • 3.4 Détacher un thread : pthread_detach()
      • 3.5 Annulation d'un thread : pthread_cancel()
    • 4. Synchronisation des threads
      • 4.1 Mutex
        • 4.1.1 Initialisation d'un mutex
        • 4.1.2 Utilisation d'un mutex : pthread_mutex_lock(), pthread_mutex_unlock()
      • 4.2 Variables conditionnelles
        • 4.2.1 Initialisation d'une variable conditionnelle
        • 4.2.2 Attendre une variable conditionnelle :pthread_cond_wait()
        • 4.2.3 Signaler un changement d'état d'une variable conditionnelle
      • Index

Auteur

Philippe BANQUETEn savoir plus

Philippe BANQUET est ingénieur informaticien indépendant depuis 1995. Spécialisé dans le développement, l'administration système et réseau ainsi que dans la formation, il a enseigné Linux et Unix auprès de nombreux informaticiens. Il a conçu et développé des applications dans les langages C, C++ et Perl, ainsi que des scripts shell. Combinant son expérience concrète de terrain et sa pratique de formateur, il utilise une démarche très pédagogique s'appuyant sur des exemples fonctionnels pour transmettre efficacement ses compétences. Il est l'auteur de plusieurs ouvrages consacrés à Linux et à la programmation.

Caractéristiques

  • Niveau Expert
  • Nombre de pages 578 pages
  • Parution septembre 2019
    • Livre (broché) - 17 x 21 cm
    • ISBN : 978-2-409-02065-0
    • EAN : 9782409020650
    • Ref. ENI : EPPRSYL
  • Niveau Expert
  • Parution septembre 2019
    • HTML
    • ISBN : 978-2-409-02066-7
    • EAN : 9782409020667
    • Ref. ENI : LNEPPRSYL

Téléchargements

En complétant ce formulaire, vous acceptez d'être contacté afin de recevoir des informations sur nos produits et services ainsi que nos communications marketing. Vous aurez la possibilité de vous désabonner de nos communications à tout moment. Pour plus d'informations sur notre politique de protection des données, cliquez ici.
  • Des fichiers complémentaires (34,8 Ko)