Vous êtes sur la page 1sur 107

5- Noyau Linux et Développement de Pilotes

Noyau Linux et Développement de Pilotes


Cours du Système Embarqué et Temps Réel

Prof. Nabil KANNOUF

UAE – ENSAH

12 novembre 2021
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes

5.2- Développement de Pilotes


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

5.2.1- Modules de noyau Linux


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Rôle d’un pilote de périphérique

Qu’est-ce qu’un pilote de périphérique ?


� Rêle du système d’exploitation (SE) : offrir une abstraction du matériel aux applica-
tions
� Pilote : partie du noyau implémentant intégration du périphérique aux abstractions du
SE
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Rôle d’un pilote de périphérique

Qu’est-ce qu’un pilote de périphérique ?


� Rêle du système d’exploitation (SE) : offrir une abstraction du matériel aux applica-
tions
� Pilote : partie du noyau implémentant intégration du périphérique aux abstractions du
SE
Implémentation selon modèle de SE
� Micro-noyau : pilote typiquement isolé dans un serveur
� Robustesse du noyau aux bogues de pilotes
� Noyau monolithique : pilote intégré à l’ensemble du noyau
� Bogue dans pilote a potentiel de faire planter tout le noyau
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Modules du noyau Linux

Module : élément du noyau pouvant être chargé et déchargé à la volée


� Modules chargés et déchargés à la volée, par exemple lors d’activation de périphériques
� Modules souvent utilisés pour implémenter pilotes de périphériques
� Rapproche Linux du fonctionnement d’un micro-noyau
� Permet d’avoir un noyau de base « minimaliste » auquel se greffent fonctionalités
optionnelles et pilotes
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Modules du noyau Linux

Module : élément du noyau pouvant être chargé et déchargé à la volée


� Modules chargés et déchargés à la volée, par exemple lors d’activation de périphériques
� Modules souvent utilisés pour implémenter pilotes de périphériques
� Rapproche Linux du fonctionnement d’un micro-noyau
� Permet d’avoir un noyau de base « minimaliste » auquel se greffent fonctionalités
optionnelles et pilotes
Module Linux est un code binaire comprenant routines, données et points d’entrée
et de sortie
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Hello, World ! d’un module de noyau

Tiré de Robert Love. Linux kernel development. Addison-Wesley, 2010.


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Hello, World ! d’un module de noyau

Tiré de Robert Love. Linux kernel development. Addison-Wesley, 2010.


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Interface de modules
Fonctions statiques d’initialisation et de terminaison
� Signature fonction d’initialisation :
static int _ _init nomfunctioninit(void)
� Appelé lors du chargement du module
� Utilisé pour activer routines et données pertinentes provenant du module
� Enregistré par la macro module_init
� Signature fonction terminaison :
static void _ _exit nomfonctionexit(void)
� Appelé lorsque module est déchargé
� Permet de retirer élément spécifique au module du noyau
� Enregistré par la macro module_exit
� Macros _ _init et _ _exit utiles pour préciser que symboles actifs seulement lors
initialisation / terminaison du module
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Interface de modules
Fonctions statiques d’initialisation et de terminaison
� Signature fonction d’initialisation :
static int _ _init nomfunctioninit(void)
� Appelé lors du chargement du module
� Utilisé pour activer routines et données pertinentes provenant du module
� Enregistré par la macro module_init
� Signature fonction terminaison :
static void _ _exit nomfonctionexit(void)
� Appelé lorsque module est déchargé
� Permet de retirer élément spécifique au module du noyau
� Enregistré par la macro module_exit
� Macros _ _init et _ _exit utiles pour préciser que symboles actifs seulement lors
initialisation / terminaison du module
Macros de description du noyau
� MODULE_LICENSE : défini licence du module
� Si module n’est pas GPL, noyau est considéré « teinté » et certains symboles uniquement
GPL ne peuvent pas être accédés
� MODULE_AUTHOR et MODULE_DESCRIPTION : à titre informatif seulement
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Compilation et chargement de modules


Modules compilés comme fichier objet
� Compilation comme fichier .o, avec en-tête du noyau
� Traitement post-compilation nécessaire pour générer fichier .ko, avec informations spécifiques
du noyau
� Détails sur compilation de modules donnés dans la séance de TP
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Compilation et chargement de modules


Modules compilés comme fichier objet
� Compilation comme fichier .o, avec en-tête du noyau
� Traitement post-compilation nécessaire pour générer fichier .ko, avec informations spécifiques
du noyau
� Détails sur compilation de modules donnés dans la séance de TP
Installation des modules
� Modules maison (fichiers .ko) dans répertoire /lib/modules/$(KERNELRELEASE)/extra/
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Compilation et chargement de modules


Modules compilés comme fichier objet
� Compilation comme fichier .o, avec en-tête du noyau
� Traitement post-compilation nécessaire pour générer fichier .ko, avec informations spécifiques
du noyau
� Détails sur compilation de modules donnés dans la séance de TP
Installation des modules
� Modules maison (fichiers .ko) dans répertoire /lib/modules/$(KERNELRELEASE)/extra/
Chargement de modules
� Commande modprobe permet chargement de module dans noyau
� Effectue vérifications d’usage sur dépendances
� Alternative : commande insmod (ne vérifie pas dépendances)
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Compilation et chargement de modules


Modules compilés comme fichier objet
� Compilation comme fichier .o, avec en-tête du noyau
� Traitement post-compilation nécessaire pour générer fichier .ko, avec informations spécifiques
du noyau
� Détails sur compilation de modules donnés dans la séance de TP
Installation des modules
� Modules maison (fichiers .ko) dans répertoire /lib/modules/$(KERNELRELEASE)/extra/
Chargement de modules
� Commande modprobe permet chargement de module dans noyau
� Effectue vérifications d’usage sur dépendances
� Alternative : commande insmod (ne vérifie pas dépendances)
Décharger modules
� Commande modprobe -r
� Alternative : rmmod (ne vérifie pas dépendances)
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Compilation et chargement de modules


Modules compilés comme fichier objet
� Compilation comme fichier .o, avec en-tête du noyau
� Traitement post-compilation nécessaire pour générer fichier .ko, avec informations spécifiques
du noyau
� Détails sur compilation de modules donnés dans la séance de TP
Installation des modules
� Modules maison (fichiers .ko) dans répertoire /lib/modules/$(KERNELRELEASE)/extra/
Chargement de modules
� Commande modprobe permet chargement de module dans noyau
� Effectue vérifications d’usage sur dépendances
� Alternative : commande insmod (ne vérifie pas dépendances)
Décharger modules
� Commande modprobe -r
� Alternative : rmmod (ne vérifie pas dépendances)
Autre commandes pertinentes
� modinfo : information sur un module
� lsmod : lister modules actuellement chargés
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.1- Modules de noyau Linux

Chargement / déchargement de module pilote de disque

Tiré de Jonathan Corbet, Alessandro Rubini et Greg Kroah-Hartman. Linux device drivers. O’Reilly Media, Inc., 2005. CC BY-SA 2.0

https ://lwn.net/Kernel/LDD3/
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

5.2.2- Développer pour le noyau


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

Développer pour le noyau

Développer pour le noyau est différent du développement d’applications usuelles


� Pas d’accès aux en-têtes et à la librairie C standard
� Pas de protection de la mémoire
� Exécution d’opérations à virgule flottante peu aisées
� Pile d’appels de petite taille (fixe)
� Synchronisation et concurrence sont omniprésentes (interruption, préemption,
multiprocesseur)
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

Développer pour le noyau

Développer pour le noyau est différent du développement d’applications usuelles


� Pas d’accès aux en-têtes et à la librairie C standard
� Pas de protection de la mémoire
� Exécution d’opérations à virgule flottante peu aisées
� Pile d’appels de petite taille (fixe)
� Synchronisation et concurrence sont omniprésentes (interruption, préemption,
multiprocesseur)
Si on produit un bogue dans du code noyau, tout peut arriver
� On travaille de « l’autre côté du miroir », protections offertes par le noyau ne sont
plus présentes
� Noyau ne peut pas s’exécuter ligne à ligne dans un débogueur
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

Développer pour le noyau

Développer pour le noyau est différent du développement d’applications usuelles


� Pas d’accès aux en-têtes et à la librairie C standard
� Pas de protection de la mémoire
� Exécution d’opérations à virgule flottante peu aisées
� Pile d’appels de petite taille (fixe)
� Synchronisation et concurrence sont omniprésentes (interruption, préemption,
multiprocesseur)
Si on produit un bogue dans du code noyau, tout peut arriver
� On travaille de « l’autre côté du miroir », protections offertes par le noyau ne sont
plus présentes
� Noyau ne peut pas s’exécuter ligne à ligne dans un débogueur
Bonnes pratiques de programmation nécessaires pour arriver à des résultats
fonctionnels
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

Pas d’en-têtes et librairie C standard

Noyau n’est pas lié à la librairie standard


� En fait, aucune librairie externe ne peut être utilisée dans le noyau
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

Pas d’en-têtes et librairie C standard

Noyau n’est pas lié à la librairie standard


� En fait, aucune librairie externe ne peut être utilisée dans le noyau
Problème « d’oeuf et de poule » : librairie C standard utilise le noyau pour ses
opérations
� Librairie C également trop grosse et inefficace pour le noyau
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

Pas d’en-têtes et librairie C standard

Noyau n’est pas lié à la librairie standard


� En fait, aucune librairie externe ne peut être utilisée dans le noyau
Problème « d’oeuf et de poule » : librairie C standard utilise le noyau pour ses
opérations
� Librairie C également trop grosse et inefficace pour le noyau
Plusieurs fonctions de la librairie C ou similaires réeimplémentés dans le noyau
� Manipulation des chaînes de caractère dans en-tête <linux/string.h>
� kmalloc : allocation dynamique de mémoire dans le noyau
� printk : sortie textuelle du noyau
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

kmalloc et kfree

kmalloc : allouer dynamiquement la mémoire dans le noyau


� size : taille en octet demandée
� flags : paramètres de l’allocation
� GFP_KERNEL : allocation normale, à utiliser par défaut
� GFP_ATOMIC : haute priorité et ne doit pas dormir, à utiliser dans gestion d’interrup-
tions (moitié supérieure) ou autre contexte non associé à un processus
� GFP_DMA : mémoire utilisable pour DMA
� Nombreux autres paramètres possibles, voir le manuel
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

kmalloc et kfree

kmalloc : allouer dynamiquement la mémoire dans le noyau


� size : taille en octet demandée
� flags : paramètres de l’allocation
� GFP_KERNEL : allocation normale, à utiliser par défaut
� GFP_ATOMIC : haute priorité et ne doit pas dormir, à utiliser dans gestion d’interrup-
tions (moitié supérieure) ou autre contexte non associé à un processus
� GFP_DMA : mémoire utilisable pour DMA
� Nombreux autres paramètres possibles, voir le manuel
kfree : libérer la mémoire
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

printk

Interface d’utilisation similaire à printf


� On peut donner directive de formatage de valeur dans la première chaîne de caractères

� printk(KERN_DEBUG "Iteration : %d \n", i)


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

printk

Interface d’utilisation similaire à printf


� On peut donner directive de formatage de valeur dans la première chaîne de caractères

� printk(KERN_DEBUG "Iteration : %d \n", i)


Ajouter niveau du message avant la première chaîne de caractères
� printk(KERN_ALERT "Ceci est une alerte ! \n")
� Niveaux possibles (0 à 7) : KERN_EMERG, KERN_ALERT, KERN_CRIT, KERN_ERR,
KERN_WARNING, KERN_NOTICE, KERN_INFO et KERN_DEBUG
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

printk

Interface d’utilisation similaire à printf


� On peut donner directive de formatage de valeur dans la première chaîne de caractères

� printk(KERN_DEBUG "Iteration : %d \n", i)


Ajouter niveau du message avant la première chaîne de caractères
� printk(KERN_ALERT "Ceci est une alerte ! \n")
� Niveaux possibles (0 à 7) : KERN_EMERG, KERN_ALERT, KERN_CRIT, KERN_ERR,
KERN_WARNING, KERN_NOTICE, KERN_INFO et KERN_DEBUG
On peut obtenir les informations par la commande dmesg
� Filtrer sortie selon mots clées : dmesg | grep MONMOTCLE
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.2- Développer pour le noyau

printk

Interface d’utilisation similaire à printf


� On peut donner directive de formatage de valeur dans la première chaîne de caractères

� printk(KERN_DEBUG "Iteration : %d \n", i)


Ajouter niveau du message avant la première chaîne de caractères
� printk(KERN_ALERT "Ceci est une alerte ! \n")
� Niveaux possibles (0 à 7) : KERN_EMERG, KERN_ALERT, KERN_CRIT, KERN_ERR,
KERN_WARNING, KERN_NOTICE, KERN_INFO et KERN_DEBUG
On peut obtenir les informations par la commande dmesg
� Filtrer sortie selon mots clées : dmesg | grep MONMOTCLE
Très (très) utile pour déboguer du développement de code pour le noyau
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

5.2.3- Primitives de synchronisation du noyau


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Primitives de synchronisation du noyau

Fonctions du noyau peuvent être exécutées de façon concurrente et réentrante


� Primitives de synchronisation POSIX non disponibles dans le noyau
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Primitives de synchronisation du noyau

Fonctions du noyau peuvent être exécutées de façon concurrente et réentrante


� Primitives de synchronisation POSIX non disponibles dans le noyau
Plusieurs mécanismes disponibles
� Entier atomique
� Spinlock
� Mutex
� Sémaphores
� Désactiver la préemption
� Variable de complétion
� Verrou sequentiel (pas présenté)
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Entier atomique

Entier atomique : permet opérations sûres sur des entiers


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Entier atomique

Entier atomique : permet opérations sûres sur des entiers


Remplacement au type C int
� Type atomic_t défini dans en-tête linux/atomic.h
� Definition : atomic_t v ;
� Instanciation : atomic_t u = ATOMIC_INIT(0) ; /* u = 0 */
� Assignation : atomic_set(&v, 4) ; /* v = 4 */
� Addition : atomic_add(2, &v) ; /* v = v + 2 */
� Incrément : atomic_inc(&v) ; /* v = v + 1 */
� Convertir : printk("%d\n", atomic_read(&v)) ; /* affiche v */
� Plusieurs autres opérations disponibles
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Entier atomique

Entier atomique : permet opérations sûres sur des entiers


Remplacement au type C int
� Type atomic_t défini dans en-tête linux/atomic.h
� Definition : atomic_t v ;
� Instanciation : atomic_t u = ATOMIC_INIT(0) ; /* u = 0 */
� Assignation : atomic_set(&v, 4) ; /* v = 4 */
� Addition : atomic_add(2, &v) ; /* v = v + 2 */
� Incrément : atomic_inc(&v) ; /* v = v + 1 */
� Convertir : printk("%d\n", atomic_read(&v)) ; /* affiche v */
� Plusieurs autres opérations disponibles
Version entier 64 bits disponible : atomic64_t
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Entier atomique

Entier atomique : permet opérations sûres sur des entiers


Remplacement au type C int
� Type atomic_t défini dans en-tête linux/atomic.h
� Definition : atomic_t v ;
� Instanciation : atomic_t u = ATOMIC_INIT(0) ; /* u = 0 */
� Assignation : atomic_set(&v, 4) ; /* v = 4 */
� Addition : atomic_add(2, &v) ; /* v = v + 2 */
� Incrément : atomic_inc(&v) ; /* v = v + 1 */
� Convertir : printk("%d\n", atomic_read(&v)) ; /* affiche v */
� Plusieurs autres opérations disponibles
Version entier 64 bits disponible : atomic64_t
Opérations atomiques sur les bits de variables également disponibles
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Spinlock

Spinlock (verrou tournant) : primitive d’exclusion mutuelle effectuant une attente active
� Consomme ressources durant attente et n’est pas récursif
� Doit être utilisé pour blocage d’une courte durée
� Utile dans sections critiques du noyau (ex. gestion des interruptions), afin de minimiser délais
d’attente
� Contrairement aux mutex, pas préempté lorsque verrou pas obtenu
� Lorsque verrou est obtenu, préemption et interruptions sont désactivées
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Spinlock de lecture/écriture
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Mutex

Mutex du noyau
� Utile lorsque attente peut être longue
� Peut se mettre en veille tout en étant en possession du verrou
� À utiliser dans partie préemptible du noyau
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Sémaphores

Sémaphores du noyau
� Bloque lorsque plus que val acquisition de la ressource
� Peut être utilisé comme un mutex, avec val = 1
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Désactiver préemption

Préemption de l’exécution dans le noyau peut être désactivée temporairement


Peut être appelé récursivement
� Appels à preempt_enable() doivent être symétriques à preempt_disable()
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.3- Primitives de synchronisation du noyau

Variable de complétion

Patron fréquent : attendre qu’une tâche se termine avant de poursuivre tâche cou-
rante
Variable de complétion permet de signaler toutes les tâches en attente d’un
résultat ou d’une tâche
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.4- Gestion des interruptions

5.2.4- Gestion des interruptions


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.4- Gestion des interruptions

Gestion des interruptions


Interruptions : moyen d’interfacer matériel avec processeur
� Signal asynchrone, reçu sur certaines broches d’entrée du processeur, pouvant interrompre le
noyau à tout moment
� Interruption associée à tout matériel externe au processeur : minuteur, clavier, disque dur,
etc.
� Chaque élément du matériel a un numéro d’interruption propre : interrupt request line
(IRQ)
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.4- Gestion des interruptions

Gestion des interruptions


Interruptions : moyen d’interfacer matériel avec processeur
� Signal asynchrone, reçu sur certaines broches d’entrée du processeur, pouvant interrompre le
noyau à tout moment
� Interruption associée à tout matériel externe au processeur : minuteur, clavier, disque dur,
etc.
� Chaque élément du matériel a un numéro d’interruption propre : interrupt request line
(IRQ)
Interruptions traitées par des routines de gestion des interruptions
� Routine s’exécute dans un contexte d’interruption, qui ne peut pas bloquer et n’est pas
préemptée
� Routine doit s’exécuter sur une courte période et retourner au contexte courant rapidement
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.4- Gestion des interruptions

Gestion des interruptions


Interruptions : moyen d’interfacer matériel avec processeur
� Signal asynchrone, reçu sur certaines broches d’entrée du processeur, pouvant interrompre le
noyau à tout moment
� Interruption associée à tout matériel externe au processeur : minuteur, clavier, disque dur,
etc.
� Chaque élément du matériel a un numéro d’interruption propre : interrupt request line
(IRQ)
Interruptions traitées par des routines de gestion des interruptions
� Routine s’exécute dans un contexte d’interruption, qui ne peut pas bloquer et n’est pas
préemptée
� Routine doit s’exécuter sur une courte période et retourner au contexte courant rapidement
Si traitement de l’interruption est long, séparer en deux moitiés
� Moitié supérieure (top-half ) : exécution rapide dans le contexte de l’interruption, pour trai-
tement minimal
� Moitié inférieure (bottom-half ) : exécution plus longue dans contexte courant (ex. kthread,
tasklet), pour compléter traitements complexes associés à l’interruption
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.4- Gestion des interruptions

Gestion des interruptions


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.4- Gestion des interruptions

Enregistrer routine gestion d’interruption

Fonction request_irq permet d’enregistrer routine de gestion de type irq_handler_t


� flags contient les propriétés selon un masque de bits
� IRQF_SHARED : plusieurs routines d’interruption peuvent être appelées par l’IRQ
� name : nom du dispositif associé à l’interruption
� dev : cookie pour identifier routine lorsque plusieurs routines partagent la gestion d’une IRQ
� Retourne 0 si succès, code d’erreur autrement
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.4- Gestion des interruptions

Enregistrer routine gestion d’interruption

Fonction request_irq permet d’enregistrer routine de gestion de type irq_handler_t


� flags contient les propriétés selon un masque de bits
� IRQF_SHARED : plusieurs routines d’interruption peuvent être appelées par l’IRQ
� name : nom du dispositif associé à l’interruption
� dev : cookie pour identifier routine lorsque plusieurs routines partagent la gestion d’une IRQ
� Retourne 0 si succès, code d’erreur autrement
irq_handler_t doit retourner valeur de type irqreturn_t
� IRQ_NONE : interruption non gérée par routine
� IRQ_HANDLED : interruption gérée par routine
� IRQ_WAKE_THREAD : thread réveillé pour faire traitement dans moitié inférieure
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.4- Gestion des interruptions

Routines de gestion d’interruption partageant IRQ

Pour utiliser plusieurs routines de gestion d’interruption d’une même IRQ


� IRQF_SHARED doit être donnée à l’argument flags de request_irq
� Argument dev doit être unique pour chaque routine et différent de NULL
� Pointeur à une structure spécifique au dispositif est suffisant
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.4- Gestion des interruptions

Routines de gestion d’interruption partageant IRQ

Pour utiliser plusieurs routines de gestion d’interruption d’une même IRQ


� IRQF_SHARED doit être donnée à l’argument flags de request_irq
� Argument dev doit être unique pour chaque routine et différent de NULL
� Pointeur à une structure spécifique au dispositif est suffisant
Routines de gestion de l’interruption appelées séquentiellement
� Chaque routine doit rapidement distinguer si elle gère l’interruption ou non
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.4- Gestion des interruptions

Routines de gestion d’interruption partageant IRQ

Pour utiliser plusieurs routines de gestion d’interruption d’une même IRQ


� IRQF_SHARED doit être donnée à l’argument flags de request_irq
� Argument dev doit être unique pour chaque routine et différent de NULL
� Pointeur à une structure spécifique au dispositif est suffisant
Routines de gestion de l’interruption appelées séquentiellement
� Chaque routine doit rapidement distinguer si elle gère l’interruption ou non
Exemple d’appel à request_irq
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.4- Gestion des interruptions

Tasklet

Tasklet : tâche devant être exécutée par le noyau à court terme


� Idéal pour exécution de la moitié inférieure d’une interruption
� Exécution dans le contexte courant du noyau
� Appel à tasklet_schedule planifie une exécution de la tâche
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

5.2.5- Dispositifs de caractères


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Classes de périphériques
Classes de périphériques dans Linux
� Dispositifs de caractères (character device)
� Échange selon un flot séquentiel de données
� Ex. port série, clavier
� Dispositif de blocs (block device)
� Accès aléatoires à des morceaux de taille fixe
� Ex. disque dur, mémoire flash
� Interface réseau
� Donner accès à un réseau
� Interface d’utilisation : socket
� Brise l’abstraction « tout est un fichier » de Unix
� Ex. carte réseau, interface Wifi, interface Bluetooth
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Classes de périphériques
Classes de périphériques dans Linux
� Dispositifs de caractères (character device)
� Échange selon un flot séquentiel de données
� Ex. port série, clavier
� Dispositif de blocs (block device)
� Accès aléatoires à des morceaux de taille fixe
� Ex. disque dur, mémoire flash
� Interface réseau
� Donner accès à un réseau
� Interface d’utilisation : socket
� Brise l’abstraction « tout est un fichier » de Unix
� Ex. carte réseau, interface Wifi, interface Bluetooth
Présentation se limite aux mécanismes pour dispositifs de caractères
� Dispositifs de blocs et interfaces réseaux ont leur propre complexité
� Voir Jonathan Corbet, Alessandro Rubini et Greg Kroah-Hartman. Linux device drivers.
O’Reilly Media, Inc., 2005. si intérêt : https ://lwn.net/Kernel/LDD3/
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Module scull
scull : Simple Character Utility for Loading Localities
� Module simple correspond à un espace mémoire accessible comme un dispositif de caractères
� Exemple académique, ne fait rien de particulièrement utile
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Module scull
scull : Simple Character Utility for Loading Localities
� Module simple correspond à un espace mémoire accessible comme un dispositif de caractères
� Exemple académique, ne fait rien de particulièrement utile
Dispositifs de caractères situés dans /dev
crw-rw-rw- 1 root root 1, 3 jan 6 14 :29 null
crw-rw-rw- 1 root root 1, 8 jan 6 14 :29 rand
crw––w–––– 1 root tty 4, 0 jan 6 14 :29 tty0
crw––w–––– 1 root tty 4, 1 jan 6 14 :29 tty1
crw-rw-rw- 1 root root 1, 9 jan 6 14 :29 urandom
crw-rw–––– 1 root tty 7, 1 jan 6 14 :29 vcs1
crw-rw–––– 1 root tty 7, 129 jan 6 14 :29 vcsa1
crw-rw-rw- 1 root root 1, 5 jan 6 14 :29 zero
� Premier caractère c désigne un dispositif de caractère
� Première et deuxième chiffires après détenteur/groupe désignent numéros majeur et mineur,
respectivement
� Numéro majeur désigne le numéro de pilote pour le noyau
� Numéro mineur est un moyen pour le pilote d’identifier le dispositif
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Obtenir numéros de dispositifs

alloc_chrdev_region : demander numéros pour dispositifs


� dev : valeur de numéro majeur et premier numéro mineur obtenu
� firstminor : premier numéro mineur demandé
� count : nombre de numéros mineurs demandés (nombre d’instances du dispositif
créés)
� name : nom du dispositif
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Obtenir numéros de dispositifs

alloc_chrdev_region : demander numéros pour dispositifs


� dev : valeur de numéro majeur et premier numéro mineur obtenu
� firstminor : premier numéro mineur demandé
� count : nombre de numéros mineurs demandés (nombre d’instances du dispositif
créés)
� name : nom du dispositif
register_chrdev_region : alloue dispositif avec numéro majeur prédéterminé
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Obtenir numéros de dispositifs

alloc_chrdev_region : demander numéros pour dispositifs


� dev : valeur de numéro majeur et premier numéro mineur obtenu
� firstminor : premier numéro mineur demandé
� count : nombre de numéros mineurs demandés (nombre d’instances du dispositif
créés)
� name : nom du dispositif
register_chrdev_region : alloue dispositif avec numéro majeur prédéterminé
unregister_chrdev_region : désallouer dispositif de caractères
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Obtenir numéros de dispositifs

alloc_chrdev_region : demander numéros pour dispositifs


� dev : valeur de numéro majeur et premier numéro mineur obtenu
� firstminor : premier numéro mineur demandé
� count : nombre de numéros mineurs demandés (nombre d’instances du dispositif
créés)
� name : nom du dispositif
register_chrdev_region : alloue dispositif avec numéro majeur prédéterminé
unregister_chrdev_region : désallouer dispositif de caractères
MKDEV : macro pour créer variable dev_t
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Opérations sur les fichiers


Rappel : dans Unix tout est un fichier
� On doit interface notre dispositif de caractères à l’interface d’accès aux fichiers
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Opérations sur les fichiers


Rappel : dans Unix tout est un fichier
� On doit interface notre dispositif de caractères à l’interface d’accès aux fichiers
Struct file_operations effectue le lien
� Pilote doit affecter ces fonctions selon les opérations implémentées

� owner doit pratiquement toujours affecée à macro THIS_MODULE


� Autres variables sont des pointeurs de fonction, à affecter si défini dans le pilote
� Dans énoncé ci-haut, fonctions llseek, read, etc. sont assignées aux fonctions du
pilote scull
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Struct file_operations
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Quelques fonctions de file_operations

llseek : changer position dans le fichier


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Quelques fonctions de file_operations

llseek : changer position dans le fichier


read : lecture de données du fichier, retourne nombre d’octets lus avec succès
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Quelques fonctions de file_operations

llseek : changer position dans le fichier


read : lecture de données du fichier, retourne nombre d’octets lus avec succès
aio_read : lecture asynchrone du fichier, si NULL alors lecture synchrone avec read
effectuée
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Quelques fonctions de file_operations

llseek : changer position dans le fichier


read : lecture de données du fichier, retourne nombre d’octets lus avec succès
aio_read : lecture asynchrone du fichier, si NULL alors lecture synchrone avec read
effectuée
write : écriture dans un fichier, retourne nombre d’octets écrits avec succès
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Quelques fonctions de file_operations

llseek : changer position dans le fichier


read : lecture de données du fichier, retourne nombre d’octets lus avec succès
aio_read : lecture asynchrone du fichier, si NULL alors lecture synchrone avec read
effectuée
write : écriture dans un fichier, retourne nombre d’octets écrits avec succès
readdir : doit rester NULL pour dispositif de caractères, utile seulement pour sys-
tèmes de fichiers
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Quelques fonctions de file_operations

llseek : changer position dans le fichier


read : lecture de données du fichier, retourne nombre d’octets lus avec succès
aio_read : lecture asynchrone du fichier, si NULL alors lecture synchrone avec read
effectuée
write : écriture dans un fichier, retourne nombre d’octets écrits avec succès
readdir : doit rester NULL pour dispositif de caractères, utile seulement pour sys-
tèmes de fichiers
ioctl : gestion de commandes spécifiques au dispositif
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Quelques fonctions de file_operations

llseek : changer position dans le fichier


read : lecture de données du fichier, retourne nombre d’octets lus avec succès
aio_read : lecture asynchrone du fichier, si NULL alors lecture synchrone avec read
effectuée
write : écriture dans un fichier, retourne nombre d’octets écrits avec succès
readdir : doit rester NULL pour dispositif de caractères, utile seulement pour sys-
tèmes de fichiers
ioctl : gestion de commandes spécifiques au dispositif
open : première opération à effectuer sur le dispositif, si NULL dispositif toujours
ouvert avec succès
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Quelques fonctions de file_operations

llseek : changer position dans le fichier


read : lecture de données du fichier, retourne nombre d’octets lus avec succès
aio_read : lecture asynchrone du fichier, si NULL alors lecture synchrone avec read
effectuée
write : écriture dans un fichier, retourne nombre d’octets écrits avec succès
readdir : doit rester NULL pour dispositif de caractères, utile seulement pour sys-
tèmes de fichiers
ioctl : gestion de commandes spécifiques au dispositif
open : première opération à effectuer sur le dispositif, si NULL dispositif toujours
ouvert avec succès
release : dernière opération à effectuer sur le dispositif, si NULL dispositif
toujours libéré avec succès
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Struct file

Fichiers dans le noyau représentés par structure file


� À ne pas confondre avec descripteur de fichier FILE
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Struct file
f_mode : mode d’ouverture du fichier, soit en lecture (FMODE_READ) et/ou écriture
(FMODE_WRITE)
� Pas besoin de vérifier pour read et write, noyau vérifie avant appel
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Struct file
f_mode : mode d’ouverture du fichier, soit en lecture (FMODE_READ) et/ou écriture
(FMODE_WRITE)
� Pas besoin de vérifier pour read et write, noyau vérifie avant appel
f_pos : position dans le fichier, défini sur un entier 64 bits ; ne pas modifier direc-
tement cette valeur, sauf pour fonction llseek
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Struct file
f_mode : mode d’ouverture du fichier, soit en lecture (FMODE_READ) et/ou écriture
(FMODE_WRITE)
� Pas besoin de vérifier pour read et write, noyau vérifie avant appel
f_pos : position dans le fichier, défini sur un entier 64 bits ; ne pas modifier direc-
tement cette valeur, sauf pour fonction llseek
f_flags : drapeaux du fichier tels que O_RDONLY, O_NONBLOCK et O_SYNC, voir
entête <linux/fcntl.h> pour liste complète
� Seul O_NONBLOCK doit être vérifié (E/S non-bloquantes)
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Struct file
f_mode : mode d’ouverture du fichier, soit en lecture (FMODE_READ) et/ou écriture
(FMODE_WRITE)
� Pas besoin de vérifier pour read et write, noyau vérifie avant appel
f_pos : position dans le fichier, défini sur un entier 64 bits ; ne pas modifier direc-
tement cette valeur, sauf pour fonction llseek
f_flags : drapeaux du fichier tels que O_RDONLY, O_NONBLOCK et O_SYNC, voir
entête <linux/fcntl.h> pour liste complète
� Seul O_NONBLOCK doit être vérifié (E/S non-bloquantes)
f_op : opérations associées au fichier courant (struct file_operations)
� Noyau assigne pointeur lors de l’appel à open
� Valeur non conservée ailleurs, modifier dans la struct file change l’effet pour le
fichier
� Utile pour changer comportement pour différentes versions du pilote (numéro mineur)
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Struct file
f_mode : mode d’ouverture du fichier, soit en lecture (FMODE_READ) et/ou écriture
(FMODE_WRITE)
� Pas besoin de vérifier pour read et write, noyau vérifie avant appel
f_pos : position dans le fichier, défini sur un entier 64 bits ; ne pas modifier direc-
tement cette valeur, sauf pour fonction llseek
f_flags : drapeaux du fichier tels que O_RDONLY, O_NONBLOCK et O_SYNC, voir
entête <linux/fcntl.h> pour liste complète
� Seul O_NONBLOCK doit être vérifié (E/S non-bloquantes)
f_op : opérations associées au fichier courant (struct file_operations)
� Noyau assigne pointeur lors de l’appel à open
� Valeur non conservée ailleurs, modifier dans la struct file change l’effet pour le
fichier
� Utile pour changer comportement pour différentes versions du pilote (numéro mineur)
private_data : pointeur aux données internes
� Peut être utilisé par le pilote pour référer à toutes données pertinentes
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Struct file
f_mode : mode d’ouverture du fichier, soit en lecture (FMODE_READ) et/ou écriture
(FMODE_WRITE)
� Pas besoin de vérifier pour read et write, noyau vérifie avant appel
f_pos : position dans le fichier, défini sur un entier 64 bits ; ne pas modifier direc-
tement cette valeur, sauf pour fonction llseek
f_flags : drapeaux du fichier tels que O_RDONLY, O_NONBLOCK et O_SYNC, voir
entête <linux/fcntl.h> pour liste complète
� Seul O_NONBLOCK doit être vérifié (E/S non-bloquantes)
f_op : opérations associées au fichier courant (struct file_operations)
� Noyau assigne pointeur lors de l’appel à open
� Valeur non conservée ailleurs, modifier dans la struct file change l’effet pour le
fichier
� Utile pour changer comportement pour différentes versions du pilote (numéro mineur)
private_data : pointeur aux données internes
� Peut être utilisé par le pilote pour référer à toutes données pertinentes
f_inode : lien vers le inode du fichier
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Struct inode

Struct inode : représentation interne du noyau d’un fichier


� Plusieurs file (descripteurs de fichier) peuvent pointer à un inode
� Struct inode contient beaucoup d’information sur le fichier, deux champs sont per-
tinents pour écrire le code d’un pilote
� dev_t i_rdev : contient numéros majeur et mineur du dispositif de caractères
� struct cdev* i_cdev : lien à la structure interne du noyau des dispositifs de caractères
� Obtenir numéros majeur et mineur du dispositif (ne pas utiliser i_rdev directement)
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Enregistrer dispositif de caractères

Deux approches pour créer structure interne du dispositif


� cdev_alloc : fait une allocation dynamique
� cdev_init : initialise une struct cdev, par exemple variable membre d’une autre struct
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Enregistrer dispositif de caractères

Deux approches pour créer structure interne du dispositif


� cdev_alloc : fait une allocation dynamique
� cdev_init : initialise une struct cdev, par exemple variable membre d’une autre struct
cdev_add : ajoute structure interne au noyau
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Enregistrer dispositif de caractères

Deux approches pour créer structure interne du dispositif


� cdev_alloc : fait une allocation dynamique
� cdev_init : initialise une struct cdev, par exemple variable membre d’une autre struct
cdev_add : ajoute structure interne au noyau
cdev_del : retire structure du noyau et, si pertinent, désalloue structure
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Exemple d’enregistrement de dispositif

Structure d’un dispositif scull


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.5- Dispositifs de caractères

Exemple d’enregistrement de dispositif

Structure d’un dispositif scull

Enregistrement de la structure au noyau


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

5.2.6- Implémentation du dispositif scull


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Fonctions open et release


open : initialiser le pilote pour opérations à venir

� Ligne 3 : container_of permet obtenir struct scull_dev contenant variable cdev


� Ligne 4 : assigner cdev à données privées
� Lignes 5-8 : réduire taille à 0 si ouvert en lecture seulement
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Fonctions open et release


open : initialiser le pilote pour opérations à venir

� Ligne 3 : container_of permet obtenir struct scull_dev contenant variable cdev


� Ligne 4 : assigner cdev à données privées
� Lignes 5-8 : réduire taille à 0 si ouvert en lecture seulement
release : libérer le dispositif
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Utilisation de la mémoire de scull


Chaque dispositif scull_dev est une liste chaînée de pointeurs (data)
� quantum et qset : taille quantum et ensemble de quantum, resp.
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Utilisation de la mémoire de scull


Chaque dispositif scull_dev est une liste chaînée de pointeurs (data)
� quantum et qset : taille quantum et ensemble de quantum, resp.
Struct scull_qset est structure de donnée d’ensemble de quantum

Tiré de Jonathan Corbet, Alessandro Rubini et Greg Kroah-Hartman. Linux device drivers. O’Reilly Media, Inc., 2005. CC BY-SA 2.0

https ://lwn.net/Kernel/LDD3/
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Libérer la mémoire de scull


read : écrire les données dans le tampon fournis par l’utilisateur
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Fonction read
Fonction scull_trim permet de libérer la mémoire utilisée

� Fonction doit écrire le résultat de la lecture dans buff


� Mais buff est alloué par l’utilisateur
� Écrire dans un espace mémoire utilisateur à partir du noyau mène à des résultats imprévisibles
� Utiliser fonctions suivantes à la place

� Comportement similaire aux fonctions memcpy


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Fonction read
Fonction scull_trim permet de libérer la mémoire utilisée

� Fonction doit écrire le résultat de la lecture dans buff


� Mais buff est alloué par l’utilisateur
� Écrire dans un espace mémoire utilisateur à partir du noyau mène à des résultats imprévisibles
� Utiliser fonctions suivantes à la place

� Comportement similaire aux fonctions memcpy


� Valeur de retour de read
� Cas optimal : retourne count octets lus
� Valeur positive mais plus petite que count : read devrait être appelé de nouveau
� Valeur 0 retournée : fin du fichier
� Valeur négative retournée : code d’erreur (voir <linux/errno.h>)
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Arguments de la fonction read

Tiré de Jonathan Corbet, Alessandro Rubini et Greg Kroah-Hartman. Linux device drivers. O’Reilly Media, Inc., 2005. CC BY-SA 2.0

https ://lwn.net/Kernel/LDD3/
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Code de la fonction read


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Code de la fonction read


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Fonction write

write : lire les données fournies par l’utilisateur et les écrire dans le dispositif

� Fonction doit lire les données de buff


� buff est alloué par l’utilisateur, donc utiliser fonction copy_from_user
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Fonction write

write : lire les données fournies par l’utilisateur et les écrire dans le dispositif

� Fonction doit lire les données de buff


� buff est alloué par l’utilisateur, donc utiliser fonction copy_from_user
� Valeur de retour de write
� Cas optimal : retourne count octets écris
� Valeur positive mais plus petite que count : write devrait être appelé de nouveau
� Valeur 0 retournée : rien d’écris, refaire l’appel (n’est pas une erreur)
� Valeur négative retournée : code d’erreur (voir <linux/errno.h>)
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Code de la fonction Write


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Code de la fonction Write


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Code de la fonction Write


5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Pilote scull complet

Code du pilote scull pratiquement complet


� Pouvez-vous dire si des parties du pilote sont manquantes ?
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Pilote scull complet

Code du pilote scull pratiquement complet


� Pouvez-vous dire si des parties du pilote sont manquantes ?
Pilote permet d’écrire et de lire dans un tampon en mémoire
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Pilote scull complet

Code du pilote scull pratiquement complet


� Pouvez-vous dire si des parties du pilote sont manquantes ?
Pilote permet d’écrire et de lire dans un tampon en mémoire
Code et explications sont tirés du chapitre 3 du livre : Jonathan Corbet, Alessandro
Rubini et Greg Kroah-Hartman. Linux device drivers. O’Reilly Media, Inc., 2005.
� Disponible au https ://lwn.net/Kernel/LDD3/
5- Noyau Linux et Développement de Pilotes
5.2- Développement de Pilotes
5.2.6- Implémentation du dispositif scull

Fin de Séance
Vos Questions ?

Vous aimerez peut-être aussi