Logs
Consultez les logs.
OK
Liste des données
Consultez la liste des données.
OK
Loading...
Formulaire
Saisissez vos données.
Enregistrer
Annuler

Drivers Linux C

Vues
424

Le but de ce tutoriel est de vous apprendre à créer des drivers en C sous Linux.
Produit par Gérard KESSE.



Introduction


Un pilote (driver en anglais) est un petit programme qui permet à un système d'exploitation de reconnaitre une composante informatique (matériel) et de pouvoir l'utiliser. En général, chaque périphérique a son propre pilote. Sans pilote, l'imprimante ou la carte graphique par exemple, ne pourraient pas être utilisées. Chaque périphérique doit avoir le pilote compatible avec le système d'exploitation installé sur la machine pour pouvoir fonctionner. C'est pour cette raison que votre imprimante par exemple est fournie avec une disquette ou un CD. Le CD contient le ou les pilotes pour l'imprimante (avec en général quelques logiciels supplémentaires). Ainsi, quand vous connectez une nouvelle imprimante, il vous suffit d'installer le pilote pour que vos logiciels puissent l'utiliser directement, sans avoir à connaître les particularités de cette imprimante. C'est la même chose pour les autres périphériques: il existe des pilotes pour les cartes graphiques, les cartes son, les numériseurs, les cartes réseau, les modems, etc. Il est donc important, quand vous installez ou réinstallez votre système d'exploitation, d'avoir tous ces pilotes sous la main, sinon vous ne pourrez pas utiliser certains de vos périphériques. Généralement, les systèmes d'exploitation sont fournis avec un ensemble de pilotes pour les périphériques les plus courants (pilotes génériques) ainsi, il arrive souvent que vous n'ayez pas à installer les pilotes pour votre carte son ou votre souris: le système d'exploitation détecte et installe les pilotes correspondants. 

image.png


Recommandations techniques


Pour tester les extraits de code dans ce tutoriel, vous aurez besoin des éléments suivants:

Un mini PC embarqué RaspberryPi.
Un compilateur C sous Linux.
Installer GCC (GNU Compiler Collection) sous Linux.


Création d'un module de noyau Linux



Définition d'une licence


Structure du répertoire source:

src
|--- readyboard.c
|--- Makefile

Définition d'une licence:
 
//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
//===============================================
MODULE_LICENSE("GPL");
//===============================================

Définition d'un auteur


Définition d'un auteur:
 
//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
//===============================================

Définition d'une description


Définition d'une description:

//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================

Gestion du chargement du module


Gestion du chargement du module:
 
//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================
static int __init GReadyBoard_init(void);
//===============================================
static int __init GReadyBoard_init(void) {
    printk("ReadyBoard: Chargement du driver de la carte ReadyBoard...\n");
    return 0;
}
//===============================================

Gestion de la fermeture du module


Gestion de la fermeture du module:

//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================
static int __init GReadyBoard_init(void);
static void __exit GReadyBoard_exit(void);
//===============================================
static int __init GReadyBoard_init(void) {
    printk("ReadyBoard: Chargement du driver de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static void __exit GReadyBoard_exit(void) {
    printk("ReadyBoard: Fermeture du driver de la carte ReadyBoard...\n");
}
//===============================================

Enregistrement de la fonction de chargement du module


Enregistrement de la fonction de chargement du module:

//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================
static int __init GReadyBoard_init(void);
static void __exit GReadyBoard_exit(void);
//===============================================
static int __init GReadyBoard_init(void) {
    printk("ReadyBoard: Chargement du driver de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static void __exit GReadyBoard_exit(void) {
    printk("ReadyBoard: Fermeture du driver de la carte ReadyBoard...\n");
}
//===============================================
module_init(GReadyBoard_init);
//===============================================

Enregistrement de la fonction de fermeture du module


Enregistrement de la fonction de fermeture du module:

//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================
static int __init GReadyBoard_init(void);
static void __exit GReadyBoard_exit(void);
//===============================================
static int __init GReadyBoard_init(void) {
    printk("ReadyBoard: Chargement du driver de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static void __exit GReadyBoard_exit(void) {
    printk("ReadyBoard: Fermeture du driver de la carte ReadyBoard...\n");
}
//===============================================
module_init(GReadyBoard_init);
module_exit(GReadyBoard_exit);
//===============================================

Création d'un module de noyau Linux


Création d'un module de noyau Linux:
 
//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================
static int __init GReadyBoard_init(void);
static void __exit GReadyBoard_exit(void);
//===============================================
static int __init GReadyBoard_init(void) {
    printk("ReadyBoard: Chargement du driver de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static void __exit GReadyBoard_exit(void) {
    printk("ReadyBoard: Fermeture du driver de la carte ReadyBoard...\n");
}
//===============================================
module_init(GReadyBoard_init);
module_exit(GReadyBoard_exit);
//===============================================

Fichier Makefile


Fichier Makefile:

#================================================
# Makefile
#================================================
obj-m += readyboard.o
#================================================
all: modules
#================================================
modules:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
#================================================

Compilation du module


Résultat:

src
|--- readyboard.c
|--- Makefile
|--- modules.order
|--- Module.symvers
|--- readyboard.mod
|--- readyboard.mod.c
|--- readyboard.mod.o
|--- readyboard.o
|--- readyboard.ko

Module:

src
|--- readyboard.ko

Compilation du module:

#================================================
# Terminal
#================================================
make
#================================================

Nettoyage des fichiers intermédiaires


Résultat:

src
|--- readyboard.c
|--- Makefile

Nettoyage de la compilation du module:

#================================================
# Terminal
#================================================
make clean
#================================================

Installation du module


Installation du module:

#================================================
# Terminal
#================================================
sudo insmod readyboard.ko
#================================================

Affichage des messages du noyau


#================================================
# Terminal
#================================================
sudo dmesg
#================================================

image.png

Limitation de l'affichage des messages du noyau:

#================================================
# Terminal
#================================================
sudo dmesg | tail
#================================================

image.png

Affichage de la liste des modules


Affichage de la liste des modules:

#================================================
# Terminal
#================================================
sudo lsmod
#================================================

image.png

Filtrage de l'affichage des modules:

#================================================
# Terminal
#================================================
sudo lsmod | grep ready
#================================================

image.png

Fermeture d'un module


Résultat:

image.png

Fermeture d'un module:

#================================================
# Terminal
#================================================
sudo rmmod readyboard
#================================================


Utilisation des numéros de périphériques Linux



Création d'un module de noyau Linux


Résultat:

image.png

Création d'un module de noyau Linux: 

//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================
static int __init GReadyBoard_init(void);
static void __exit GReadyBoard_exit(void);
//===============================================
static int __init GReadyBoard_init(void) {
    printk("ReadyBoard: Chargement du driver de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static void __exit GReadyBoard_exit(void) {
    printk("ReadyBoard: Fermeture du driver de la carte ReadyBoard...\n");
}
//===============================================
module_init(GReadyBoard_init);
module_exit(GReadyBoard_exit);
//===============================================

Gestion de l'ouverture du système de fichier


Gestion de l'ouverture du système de fichier:

//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================
static int __init GReadyBoard_init(void);
static void __exit GReadyBoard_exit(void);
static int GReadyBoard_open(struct inode *device_file, struct file *instance);
//===============================================
static int __init GReadyBoard_init(void) {
    printk("ReadyBoard: Chargement du driver de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static void __exit GReadyBoard_exit(void) {
    printk("ReadyBoard: Fermeture du driver de la carte ReadyBoard...\n");
}
//===============================================
static int GReadyBoard_open(struct inode *device_file, struct file *instance) {
    printk(KERN_INFO "ReadyBoard: Ouverture du système de fichier de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
module_init(GReadyBoard_init);
module_exit(GReadyBoard_exit);
//===============================================

Gestion de la fermeture du système de fichier


Gestion de la fermeture du système de fichier:
  
//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================
static int __init GReadyBoard_init(void);
static void __exit GReadyBoard_exit(void);
static int GReadyBoard_open(struct inode *device_file, struct file *instance);
static int GReadyBoard_close(struct inode *device_file, struct file *instance);
//===============================================
static int __init GReadyBoard_init(void) {
    printk("ReadyBoard: Chargement du driver de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static void __exit GReadyBoard_exit(void) {
    printk("ReadyBoard: Fermeture du driver de la carte ReadyBoard...\n");
}
//===============================================
static int GReadyBoard_open(struct inode *device_file, struct file *instance) {
    printk(KERN_INFO "ReadyBoard: Ouverture du système de fichier de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static int GReadyBoard_close(struct inode *device_file, struct file *instance) {
    printk(KERN_INFO "ReadyBoard: Fermeture du système de fichier de la carte ReadyBoard...\n");
	return 0;
}
//===============================================
module_init(GReadyBoard_init);
module_exit(GReadyBoard_exit);
//===============================================

Initialisation de la gestion de l'ouverture du système de fichier


Initialisation de la gestion de l'ouverture du système de fichier:
 
//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================
static int __init GReadyBoard_init(void);
static void __exit GReadyBoard_exit(void);
static int GReadyBoard_open(struct inode *device_file, struct file *instance);
static int GReadyBoard_close(struct inode *device_file, struct file *instance);
//===============================================
static struct file_operations fops = {
    .owner = THIS_MODULE
    , .open = GReadyBoard_open
};
//===============================================
static int __init GReadyBoard_init(void) {
    printk("ReadyBoard: Chargement du driver de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static void __exit GReadyBoard_exit(void) {
    printk("ReadyBoard: Fermeture du driver de la carte ReadyBoard...\n");
}
//===============================================
static int GReadyBoard_open(struct inode *device_file, struct file *instance) {
    printk(KERN_INFO "ReadyBoard: Ouverture du système de fichier de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static int GReadyBoard_close(struct inode *device_file, struct file *instance) {
    printk(KERN_INFO "ReadyBoard: Fermeture du système de fichier de la carte ReadyBoard...\n");
	return 0;
}
//===============================================
module_init(GReadyBoard_init);
module_exit(GReadyBoard_exit);
//===============================================

Initialisation de la gestion de la fermeture du système de fichier


Initialisation de la gestion de la fermeture du système de fichier:

//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================
static int __init GReadyBoard_init(void);
static void __exit GReadyBoard_exit(void);
static int GReadyBoard_open(struct inode *device_file, struct file *instance);
static int GReadyBoard_close(struct inode *device_file, struct file *instance);
//===============================================
static struct file_operations fops = {
    .owner = THIS_MODULE
    , .open = GReadyBoard_open
    , .release = GReadyBoard_close
};
//===============================================
static int __init GReadyBoard_init(void) {
    printk("ReadyBoard: Chargement du driver de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static void __exit GReadyBoard_exit(void) {
    printk("ReadyBoard: Fermeture du driver de la carte ReadyBoard...\n");
}
//===============================================
static int GReadyBoard_open(struct inode *device_file, struct file *instance) {
    printk(KERN_INFO "ReadyBoard: Ouverture du système de fichier de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static int GReadyBoard_close(struct inode *device_file, struct file *instance) {
    printk(KERN_INFO "ReadyBoard: Fermeture du système de fichier de la carte ReadyBoard...\n");
	return 0;
}
//===============================================
module_init(GReadyBoard_init);
module_exit(GReadyBoard_exit);
//===============================================

Enregistrement d'un numéro majeur de périphérique


Enregistrement d'un numéro majeur de périphérique:

//===============================================
// readyboard.c
//===============================================
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
//===============================================
#define READY_BOARD_MAJOR   90
#define READY_BOARD_MINOR   0
//===============================================
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerard KESSE [ReadyDev]");
MODULE_DESCRIPTION("Driver de la carte ReadyBoard");
//===============================================
static int __init GReadyBoard_init(void);
static void __exit GReadyBoard_exit(void);
static int GReadyBoard_open(struct inode *device_file, struct file *instance);
static int GReadyBoard_close(struct inode *device_file, struct file *instance);
//===============================================
static struct file_operations fops = {
    .owner = THIS_MODULE
    , .open = GReadyBoard_open
    , .release = GReadyBoard_close
};
//===============================================
static int __init GReadyBoard_init(void) {
    int retval;
    
    printk(KERN_INFO "ReadyBoard: Chargement du driver de la carte ReadyBoard...\n");
    
    retval = register_chrdev(READY_BOARD_MAJOR
        , "readyboard"
        , &fops);

	if(retval == 0) {
        printk(KERN_INFO "ReadyBoard: Numéro de périphérique enregistré Majeur: %d, Mineur: %d\n"
        , READY_BOARD_MAJOR
        , READY_BOARD_MINOR);	
    }
	else if(retval > 0) {
        printk(KERN_INFO "ReadyBoard: Numéro de périphérique enregistré Majeur: %d, Mineur: %d\n"
        , retval>>20
        , retval&0xFFFFF);	
	}
	else {
        printk("ReadyBoard: Impossible d'enregistrer le numéro de périphérique !\n");
	    return -1;
	}
    return 0;
}
//===============================================
static void __exit GReadyBoard_exit(void) {
    printk("ReadyBoard: Fermeture du driver de la carte ReadyBoard...\n");
}
//===============================================
static int GReadyBoard_open(struct inode *device_file, struct file *instance) {
    printk(KERN_INFO "ReadyBoard: Ouverture du système de fichier de la carte ReadyBoard...\n");
    return 0;
}
//===============================================
static int GReadyBoard_close(struct inode *device_file, struct file *instance) {
    printk(KERN_INFO "ReadyBoard: Fermeture du système de fichier de la carte ReadyBoard...\n");
	return 0;
}
//===============================================
module_init(GReadyBoard_init);
module_exit(GReadyBoard_exit);
//===============================================

Affichage des périphériques Linux


Résultat:

image.png

Affichage des périphériques Linux: 

#================================================
# Terminal
#================================================
ls /dev
#================================================

Affichage des numéros de périphériques (1)


Résultat:

image.png

Affichage des numéros de périphériques (1):

#================================================
# Terminal
#================================================
ls -al /dev/tty*
#================================================

Affichage des numéros de périphériques (2)


Résultat:

image.png

Affichage des numéros de périphériques (2): 

#================================================
# Terminal
#================================================
cat /proc/devices
#================================================