80
15/09/2013 1/ Atelier noyau & drivers du 16/10/2013

Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 1 /

Atelier noyau & driversdu 16/10/2013

Page 2: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 2 /

Points abordés

●Présentation du noyau

●Gestion de la mémoire

●Squelette d'un module dynamique

●Chargement / déchargement

●Passage de paramètres

●Import / export de symbols

Page 3: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 3 /

1. Présentation du noyau GNU/linux

Page 4: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 4 /

Rôle du noyau�GNU (GNU is Not Unix) Linux est le coeur du système. Il fournit une API basse dépendant de l’architecture au hardware et une

�Il gère aussi l’ordonnancement des tâches rendant ce dernier :

• multi-tâches : adapté au systèmes SMP, multi-coeur ou répartis ;• préemptif (davantage en 2.6 qu'en 2.4) : L'ordonnanceur distribue le temps du • multi-utilisateurs : capacité du système à disposé de plusieurs utilisateurs

�Cependant il n'est pas nativement temps réel. Pour ce faire il faut rajouter un microkernel temps réel tel que RTAI, RTLINUX

�Le noyau manage les tâches tant en espace noyau qu'en espace utilisateur.

�Vue de l'espace user, le noyau peut être contacté via un ensemble d'appels systèmesréférencés dans la librairie C (glibc).

Page 5: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 5 /

Linux temps réel

Ordonnancement dans le noyau standard

Préemptif mais pas temps réel !!

→ du temps réel mou possible maispour le temps réel dur, xenomai ou rtlinuxest nécessaire.

Utilisation d'un micro-noyau temps réel

Page 6: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 6 /

Linux temps réel

Page 7: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 7 /

USER / KERNEL�Utilisation de la protection matérielle du microprocesseur

�Différence entre les deux mondes :

➔Espace noyau : où tout est autorisé même le pire (moins de restrictions)• Accès à toutes les ressources en direct ;• Espace privilégié ;

• Utilisé par les entrées et sorties

➔Espace utilisateur : accès plus restreint• Espace non-privilégié ;• Accès restreint aux ressources ;• Pas d’accès direct aux entrées et sorties ;• Passage obligé par le noyau

�Tout processus au cours de son exécution passe d’un espace à l’autre. La transition sefaisant via :

• la SCI qui est la frontière entre les deux mondes (c’est l’API publique normalisé par la norme POSIX offerte par le noyau a• les interruptions issue de timers, entrées et sorties, etc ...• Les exceptions issue du processeur (accès illégal à la mémoire, instruction illégale, etc ... )

Page 8: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 8 /

Espace User / Kernel

Le but de la SCI est d'offrir une API publique au noyau vers l'espace utilisateur

Elle détaille les syscall qui sont mappés vers la libc

La libc sert de couche d'abstraction et de tampon

Page 9: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 9 /

Page 10: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 10 /

Page 11: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 11 /

Découpage du noyau

Découpage modulaire du noyau GNU/Linux

Page 12: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 12 /

Virtual File System (aka VFS)

Page 13: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 13 /

Virtual File System�Linux n'étant pas monolithique c'est-à dire qu'il est constitué d'un ensemble de parties comme la pile

�VFS est la couche d'abstraction de hautNiveau intra-kernel regroupant un ensemble de primitives génériques comme open, close, read, write

●S'il s'agit d'écrire un fichier (une fifo ou autre) sur un disque, hé bien l'implémentation dans le kernel

Page 14: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 14 /

Représentation de VFS

Page 15: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 15 /

Systèmes de fichiers disponibles sous Linux :

Page 16: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 16 /

Standard Call Interface(aka SCI)

Page 17: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 17 /

Détail d'un appel système user → kernel

Page 18: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 18 /

Déroulement d'une session de login :

Page 19: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 19 /

Process Management(aka PM)

Page 20: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 20 /

Page 21: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 21 /

Network Stack(aka PM)

Page 22: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 22 /

Atelier boot d'un noyaudans QEMU

→ Le but de cet atelier sera de comprendre comment booter un noyau et un rootfsdans QEMU.

Répertoire : atelier/_qemu/

Page 23: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 23 /

Rootfs (généré par buildroot)Arch : x86

Image : rootfs.ext2Fs : ext2

Noyau GNU/LinuxArch : x86

Image : bzImage_testCompressé : oui

qemu-system-i386Arch : x86

Qemu joue de rôle de :- d'une board enl'émulant

- d'un bootloader

$ qemu-system-i386 -kernel bzImage_test \-append root="/dev/sda" \-hda rootfs.ext2

Noyau gnu/linux

Paramètres passés au noyau

Rootfs

Chargement et initialisation du noyau GNU/LinuxInitialisation du rootfspar le noyau

Page 24: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 24 /

Login = rootMot de passe = aucun

Page 25: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 25 /

Si la machine compilant les sources possède plus d'un processeur ou core, il est possible de paralléliser la génération en utilisant

L'option -j définit le nombre maximal de tâche en parallèles qui peuvent être exécutées par le makefile et l'option -l empêche toute

Pour savoir combien il est possible de paralléliser, un calcul simple est facile à faire :

$ export NBCOEUR=$(($(grep -c processor /proc/cpuinfo)+1 ))ou$ export NBCOEUR=$(($(cat /proc/cpuinfo|grep processor| wc -l)+1))

Pour un INTEL core I7 cela donne 9 et pour un INTEL core I3 cela donne 5.

Pour avoir une génération qui puisse d'adapter de façon optimum à la machine où sont compilés les sources du noyau linux, les

$ export NBCOEUR=$(($(cat /proc/cpuinfo | grep processor | wc -l)+1))$ make –jobs=$((NBCOEUR+1)) --load-average=${NBCOEUR}

A noter également que la génération peut être lance même si l'on ne se trouve pas dans le répertoire des sources. En effet, comme

$ make -j 9 -C=~/linux_src/

Compilation du noyau GNU/Linux

Page 26: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 26 /

Atelier compilation de module dynamique

→ Le but de cet atelier sera de compiler un drivers en dehors des sources

du noyau linux en écrivant un Makefile.

Nous allons également comprendre ce qui est généré et aussi comment.

Répertoire : atelier/_makefile/

Page 27: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 27 /

Vérifions notre environnement :

$ uname -r3.2.0-53-generic-pae

Nous devons avoir les headers du noyau courant :

$ ls -al /lib/modules/total 116drwxr-xr-x 27 root root 4096 oct. 7 09:14 .drwxr-xr-x 27 root root 12288 oct. 4 16:41 ..drwxr-xr-x 4 root root 4096 oct. 3 18:31 3.2.0-52-genericdrwxr-xr-x 6 root root 4096 oct. 3 18:28 3.2.0-52-generic-paedrwxr-xr-x 2 root root 4096 sept. 12 14:16 3.2.0- 53-genericdrwxr-xr-x 5 root root 4096 oct. 3 18:32 3.2.0- 53-generic-paedrwxr-xr-x 2 root root 4096 oct. 7 09:14 3.2.0-54-genericdrwxr-xr-x 4 root root 4096 oct. 7 09:15 3.2.0-54-generic-paedrwxr-xr-x 3 root root 4096 août 30 12:47 3.2.48

Page 28: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 28 /

$ ls -al /lib/modules/`uname -r`/build/total 1116drwxr-xr-x 7 root root 4096 oct. 10 18:55 .drwxrwsr-x 64 root src 4096 oct. 7 09:14 ..drwxr-xr-x 3 root root 4096 sept. 12 14:16 archlrwxrwxrwx 1 root root 31 août 23 00:30 block -> ../linux-headers-3.2.0-53/block-rw-r--r-- 1 root root 147548 août 23 00:29 .config-rw-r--r-- 1 root root 147587 août 23 00:29 .config.oldlrwxrwxrwx 1 root root 32 août 23 00:30 crypto -> ../linux-headers-3.2.0-53/cryptolrwxrwxrwx 1 root root 39 août 23 00:29 Documentation -> ../linux-headers-3.2.0-53/Documentationlrwxrwxrwx 1 root root 33 août 23 00:29 drivers -> ../linux-headers-3.2.0-53/driverslrwxrwxrwx 1 root root 34 août 23 00:29 firmware -> ../linux-headers-3.2.0-53/firmwarelrwxrwxrwx 1 root root 28 août 23 00:30 fs -> ../linux-headers-3.2.0-53/fsdrwxr-xr-x 5 root root 4096 sept. 12 14:16 includelrwxrwxrwx 1 root root 30 août 23 00:29 init -> ../linux-headers-3.2.0-53/initlrwxrwxrwx 1 root root 29 août 23 00:30 ipc -> ../linux-headers-3.2.0-53/ipclrwxrwxrwx 1 root root 32 août 23 00:30 Kbuild -> ../linux-headers-3.2.0-53/Kbuildlrwxrwxrwx 1 root root 33 août 23 00:29 Kconfig -> ../linux-headers-3.2.0-53/Kconfigdrwxr-xr-x 2 root root 4096 sept. 12 14:16 kernellrwxrwxrwx 1 root root 29 août 23 00:29 lib -> ../linux-headers-3.2.0-53/liblrwxrwxrwx 1 root root 34 août 23 00:29 Makefile -> ../linux-headers-3.2.0-53/Makefile-rw-r--r-- 1 root root 509 août 23 00:29 .missing-syscalls.dlrwxrwxrwx 1 root root 28 août 23 00:30 mm -> ../linux-headers-3.2.0-53/mm-rw-r--r-- 1 root root 804726 août 23 00:30 Module.symverslrwxrwxrwx 1 root root 29 août 23 00:29 net -> ../linux-headers-3.2.0-53/netlrwxrwxrwx 1 root root 33 août 23 00:29 samples -> ../linux-headers-3.2.0-53/samplesdrwxr-xr-x 7 root root 4096 oct. 10 18:49 scriptslrwxrwxrwx 1 root root 34 août 23 00:30 security -> ../linux-headers-3.2.0-53/securitylrwxrwxrwx 1 root root 31 août 23 00:29 sound -> ../linux-headers-3.2.0-53/sounddrwxr-xr-x 2 root root 4096 août 23 00:29 .tmp_versionslrwxrwxrwx 1 root root 31 août 23 00:30 tools -> ../linux-headers-3.2.0-53/toolslrwxrwxrwx 1 root root 32 août 23 00:30 ubuntu -> ../linux-headers-3.2.0-53/ubuntulrwxrwxrwx 1 root root 29 août 23 00:29 usr -> ../linux-headers-3.2.0-53/usrlrwxrwxrwx 1 root root 30 août 23 00:30 virt -> ../linux-headers-3.2.0-53/virt

Page 29: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 29 /

Ecrivons un squelette de drivers « stubdriver.c » :

#include <linux/module.h>#include <linux/init.h>

MODULE_AUTHOR("eurogiciel");MODULE_DESCRIPTION("tp_makefile");MODULE_LICENSE("none");

static int __init mon_module_init (void){

printk(KERN_DEBUG "Hello World !\n");return 0;

}

static void __exit mon_module_cleanup (void){

printk(KERN_DEBUG "Goodbye World!\n");}

module_init(mon_module_init );module_exit(mon_module_cleanup );

callback d'init appeléeau chargement du module

callback de cleanappelée audéchargementdu module

servira à personnalisé le fichier «auto-généré

→ Pas besoin de plus pour réaliser un squelette de driver !!

Page 30: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 30 /

Écrivons notre premier Makefile :

obj-m := stubdriver.oKDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)

all:make SUBDIRS=$(PWD) -C $(KDIR) modules

install:make SUBDIRS=$(PWD) -C $(KDIR) modules_install/sbin/depmod -a

clean:make SUBDIRS=$(PWD) -C $(KDIR) clean

http://www.mjmwired.net/kernel/Documentation/kbuild/modules.txt

Nom du fichier source ; pour xxx. le Makefilecherchera xxx.c ; pour un module un seulfichier n'est accepté

Localisation du chemin courant

Localisation du chemincourant contenant le Makefiledu noyau Linux avec lesRègles de génération

Page 31: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 31 /

$ ls -altotal 16drwx------ 2 tgayet tgayet 4096 oct. 14 12:04 .drwx------ 7 tgayet tgayet 4096 oct. 14 11:31 ..-rw-r--r-- 1 tgayet tgayet 255 oct. 14 11:33 Makefile-rw-r--r-- 1 tgayet tgayet 301 oct. 14 12:03 stubdriver.c

$ make

$ ls -altotal 100drwx------ 3 tgayet tgayet 4096 oct. 14 12:04 .drwx------ 7 tgayet tgayet 4096 oct. 14 11:31 ..-rw-r--r-- 1 tgayet tgayet 255 oct. 14 11:33 Makefile-rw-r--r-- 1 tgayet tgayet 48 oct. 14 12:04 modules.order-rw-r--r-- 1 tgayet tgayet 0 oct. 14 12:04 Module.symvers-rw-r--r-- 1 tgayet tgayet 301 oct. 14 12:03 stubdriver.c-rw-r--r-- 1 tgayet tgayet 2447 oct. 14 12:04 stubdriver.ko-rw-r--r-- 1 tgayet tgayet 279 oct. 14 12:04 .stubdriver.ko.cmd-rw-r--r-- 1 tgayet tgayet 663 oct. 14 12:04 stubdriver.mod.c-rw-r--r-- 1 tgayet tgayet 1764 oct. 14 12:04 stubdriver.mod.o-rw-r--r-- 1 tgayet tgayet 26344 oct. 14 12:04 .stubdriver.mod.o.cmd-rw-r--r-- 1 tgayet tgayet 1196 oct. 14 12:04 stubdriver.o-rw-r--r-- 1 tgayet tgayet 26241 oct. 14 12:04 .stubdriver.o.cmddrwx------ 2 tgayet tgayet 4096 oct. 14 12:04 .tmp_versions

Mon driver

KO = kernel object

AVANT

APRES

Page 32: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 32 /

$ file ./drv_skel.ko

./drv_skel.ko: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), BuildID[sha1]=0x7ef13c8a0bfdee4b51be2b1f442dfdf61114e8

$ modinfo stubdriver.ko

filename: stubdriver.kolicense: nonedescription: tp_makefileauthor: eurogicielsrcversion: B10C3AD719B381C57D9FC0Bdepends: vermagic: 3.2.0-53-generic-pae SMP mod_unload modversions 686

$ cat modules.order

kernel//media/9DA1-2D6A/_makefile/stubdriver.ko→ servira au merge pour le fichier de dépendances utilisé par modprobe

Page 33: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 33 /

$ cat stubdriver.mod.c

#include <linux/module.h>#include <linux/vermagic.h>#include <linux/compiler.h>

MODULE_INFO(vermagic, VERMAGIC_STRING);

struct module __this_module__attribute__((section(".gnu.linkonce.this_module"))) = {.name = KBUILD_MODNAME,.init = init_module,

#ifdef CONFIG_MODULE_UNLOAD.exit = cleanup_module,

#endif.arch = MODULE_ARCH_INIT,

};

static const struct modversion_info ____versions[]__used__attribute__((section("__versions"))) = {

{ 0x62d5535d, "module_layout" },{ 0x50eedeb8, "printk" },

};

static const char __module_depends[]__used__attribute__((section(".modinfo"))) ="depends=";

MODULE_INFO(srcversion, "B10C3AD719B381C57D9FC0B");

Callback de déchargement

Callback de chargement

Nom du module qui sera affiché dans lsmod

Aucune dépendance à un symbole externe, àUn autre drivers

CONFIG_MODULE_UNLOAD : permet de gérer le déchargement des modules dynamiques

Page 34: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 34 /

$ cat Module.symvers→ ce fichier et vide car il contient les symboles exportés par le module (ici aucun)

Refaite l'atelier avec le makefile suivant :http://www.nextinnovation.org/doku.php?id=linux_kernel_makefile_ref

ps : au préalable renommez l'ancien makefile → Makefile.old

Vous remarquerez le différentiel quant au niveau du nommage via la commandemodinfo :

$ modinfo drv_skel.ko

Page 35: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 35 /

Atelier chargement/déchargement

de drivers

→ Le but de cet atelier sera de comprendre comment sont chargés ou

déchargés les drivers dans le noyau GNU/Linux soit de façon manuelle

ou bien automatique avec gestion de dépendance.

Répertoire : atelier/_refMakefile/

Page 36: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 36 /

→ Le chargement d'un driverpeut être assimiler au chargementdynamique d'une librairiedynamique.

→ On retrouve les fonctions decallback associés aux modulesdynamiques.

→ La callback d'init sert à initialiserle fonctionnement d'un drivers alorsque la callback de clean sert àlibérer les ressources allouésprécédemment.

Page 37: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 37 /

En restant dur l'atelier précédant, regardons le contexte avant chargement :

$ ls -al *.ko-rw-r--r-- 1 tgayet tgayet 2605 oct. 14 13:29 drv_skel.ko→ un seul kernel object pouvant être chargé

$ lsmod | grep drv_skel→ lsmod permet de lister les modules charges dans l'espace noyau

Chargeons le drivers manuellement :

sudo insmod ./drv_skel.ko→ insmod permet de charger un module dynamique en précisant son path et son extension .ko

$ lsmod | grep drv_skeldrv_skel 12401 0→ On remarque la taille du driver et son utilisation, ici même zéro

Déchargeons le manuellement :

$ sudo rmmod ./drv_skel.ko→ rmmod permet de décharger un module dynamique de façon similaire à insmod

$ lsmod | grep drv_skel→ Le listing sur ce noyau est vide

Méthode manuelle avec insmod / rmmod

Page 38: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 38 /

Vérifions le chemin des modules dynamiques pour notre noyau GNU/Linux :

$ ls -al /lib/modules/`uname -r`/

total 4532drwxr-xr-x 5 root root 4096 oct. 3 18:32 .drwxr-xr-x 27 root root 4096 oct. 7 09:14 ..lrwxrwxrwx 1 root root 43 août 23 00:30 build -> /usr/src/linux-headers-3.2.0-53-generic-paedrwxr-xr-x 2 root root 4096 sept. 12 14:15 initrddrwxr-xr-x 10 root root 4096 sept. 12 14:15 kernel-rw-r--r-- 1 root root 716580 oct. 3 18:32 modules.alias-rw-r--r-- 1 root root 698012 oct. 3 18:32 modules.alias.bin-rw-r--r-- 1 root root 6185 août 23 00:27 modules.builtin-rw-r--r-- 1 root root 7657 oct. 3 18:32 modules.builtin.bin-rw-r--r-- 1 root root 69 oct. 3 18:32 modules.ccwmap-rw-r--r-- 1 root root 336595 oct. 3 18:32 modules.dep-rw-r--r-- 1 root root 497267 oct. 3 18:32 modules.dep.bin-rw-r--r-- 1 root root 186 oct. 3 18:32 modules.devname-rw-r--r-- 1 root root 889 oct. 3 18:32 modules.ieee1394map-rw-r--r-- 1 root root 295 oct. 3 18:32 modules.inputmap-rw-r--r-- 1 root root 21740 oct. 3 18:32 modules.isapnpmap-rw-r--r-- 1 root root 1421 oct. 3 18:32 modules.ofmap-rw-r--r-- 1 root root 137816 août 23 00:27 modules.order-rw-r--r-- 1 root root 455736 oct. 3 18:32 modules.pcimap-rw-r--r-- 1 root root 1765 oct. 3 18:32 modules.seriomap-rw-r--r-- 1 root root 131 oct. 3 18:32 modules.softdep-rw-r--r-- 1 root root 282504 oct. 3 18:32 modules.symbols-rw-r--r-- 1 root root 354066 oct. 3 18:32 modules.symbols.bin-rw-r--r-- 1 root root 1053428 oct. 3 18:32 modules.usbmapdrwxr-xr-x 3 root root 4096 oct. 3 18:32 updates

Fichier de déclaration des modules dynamique et de dépendances

Page 39: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 39 /

Installons notre module dynamique :

$ modprobe -l | grep drv_skel→ Avant l'installation, ce fichier ne référencie pas notre module dynamique

$ sudo make install

[sudo] password for tgayet:Current kernel version : 3.2.0-53-generic-pae--> Start compiling ...make[1]: entrant dans le répertoire « /usr/src/linux-headers-3.2.0-53-generic-pae »

CC [M] /media/9DA1-2D6A/atelier/_refMakefile/stubdriver.oLD [M] /media/9DA1-2D6A/atelier/_refMakefile/drv_skel.oBuilding modules, stage 2.MODPOST 1 modulesCC /media/9DA1-2D6A/atelier/_refMakefile/drv_skel.mod.oLD [M] /media/9DA1-2D6A/atelier/_refMakefile/drv_skel.ko

make[1]: quittant le répertoire « /usr/src/linux-headers-3.2.0-53-generic-pae »filename: drv_skel.kolicense: nonedescription: tp_makefileauthor: eurogicielsrcversion: B10C3AD719B381C57D9FC0Bdepends: vermagic: 3.2.0-53-generic-pae SMP mod_unload modversions 686<-- Compiling : done--> Start installation ...make[1]: entrant dans le répertoire « /usr/src/linux-headers-3.2.0-53-generic-pae »

INSTALL /media/9DA1-2D6A/atelier/_refMakefile/drv_skel.koDEPMOD 3.2.0-53-generic-pae

make[1]: quittant le répertoire « /usr/src/linux-headers-3.2.0-53-generic-pae »-------------------------------------------------------Arborescence dans /lib/modules/3.2.0-53-generic-pae/ :extra/drv_skel.ko<-- Installation : done

Page 40: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 40 /

Le fichier de dépendance a été mis à jour (336595 → 336614) :

$ ls -al /lib/modules/`uname -r`/modules.dep-rw-r--r-- 1 root root 336614 oct. 14 14:25 /lib/modules/3.2.0-53-generic-pae/modules.dep

Une nouvelle entrée est apparue dans ce fichier :

$ cat /lib/modules/`uname -r`/modules.dep | grep drv_skelextra/drv_skel.ko:→ le fichier « modules.dep » le référencie désormais avec son path mais ne donne pas de dépendances avec d'autres drivers.→ il est donc localisé dans le chemin suivant : /lib/modules/3.2.0-53-generic- pae/extra/drv_skel.ko

On vérifie bien l'installation du module dynamique :

$ tree /lib/modules/`uname -r`/extra//lib/modules/3.2.0-53-generic-pae/extra/└── drv_skel.ko

0 directories, 1 file

Page 41: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 41 /

Méthode automatique avec modprobe / modprobe -r

Même prérequit avant chargement :

$ lsmod | grep drv_skel

Chargement du module dynamique

$ sudo modprobe drv_skel→ se base sur le fichier « modules.dep » courant→ modprobe fera le même chose qu'un insmod avec la commande suivante :

$ sudo insmod /lib/modules/3.2.0-53-generic-pae/ext ra/drv_skel.ko→ Si déjà déchargé, ne retournera pas d'erreurs.

$ lsmod | grep drv_skeldrv_skel 12401 0

Déchargement du module dynamique :

$ sudo modprobe --remove drv_skel

$ lsmod | grep drv_skel

Page 42: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 42 /

Passage de paramètresà un module dynamique

→ Le but de cet atelier sera de comprendre comment passer des paramètres

à un modules dynamique

Répertoire : atelier/_parameters/

Page 43: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 43 /

Partons du code suivant :

#include <linux/init.h>#include <linux/module.h>#include <linux/moduleparam.h>

MODULE_LICENSE("Dual BSD/GPL");

// Définition du contexte initial (global) :static char* whom = "world";static int howmany = 1;

// Surcharge du contexte par les paramètres passés au module dynamiquemodule_param(howmany, int, S_IRUGO);module_param(whom, charp, S_IRUGO);

static int hello_init (void){

int i;

for ( i = 0; i < howmany ; i++)printk(KERN_ALERT "(%d) Hello, %s\n", i, whom );

return 0;}

static void hello_exit (void){

printk(KERN_ALERT "Goodbye, cruel world\n");}

module_init(hello_init );module_exit(hello_exit );

Nouveau header

Page 44: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 44 /

Pour commencer, compilons le module :

$ make

Current kernel version : 3.2.0-53-generic-pae--> Start compiling...filename: drvparam.kolicense: Dual BSD/GPLsrcversion: 3A3EFEF9DC82F36C7DD26B1depends: vermagic: 3.2.0-53-generic-pae SMP mod_unload modversions 686parm: howmany:intparm: whom:charp<-- Compiling : done

Page 45: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 45 /

Chargement du module dynamique sans paramètres :

$ sudo insmod ./drvparam.ko[sudo] password for tgayet:

$ lsmod | grep drvparamdrvparam 12623 0

On remarque les 2 paramètres déclarés :

$ tree /sys/module/drvparam/parameters/

/sys/module/drvparam/parameters/├── howmany└── whom

Le module est rattaché à son contexte initial :

$ cat /sys/module/drvparam/parameters/ howmany1$ cat /sys/module/drvparam/parameters/ whomworld

Page 46: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 46 /

Lecture de trace issue du noyau :

$ dmesg(...)[1113572.005947] (0) Hello, world[1114266.292223] Goodbye, cruel world

Déchargeons le drivers :

$ sudo rmmod ./drvparam.ko$ lsmod | grep drvparam

Page 47: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 47 /

Chargement avec paramètres :

$ sudo insmod ./drvparam.ko howmany=3 whom=thierry

$ lsmod | grep drvparamdrvparam 12623 0

Vérifions les données du drivers :

$ cat /sys/module/drvparam/parameters/ whomthierry

$ cat /sys/module/drvparam/parameters/ howmany3

$ dmesg(…)[1114549.334019] (0) Hello, thierry[1114549.334025] (1) Hello, thierry[1114549.334028] (2) Hello, thierry

Page 48: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 48 /

Export de symbols

→ Le but de cet atelier sera de comprendre comment exporter un symbole

dans un module et de l'utiliser dans un autre.

Répertoire : atelier/_symbol/

Page 49: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 49 /

Soit la fonction fonction_hello exportée par un module drv_export et utilisé par un second drv_import

$ cat export_api.h

#ifndef EXPORT_SYMBOLE_H

#define EXPORT_SYMBOLE_H

void fonction_hello (int numero);

#endif

drv_export.ko

fonction_hello

drv_import.ko

Page 50: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 50 /

#include <linux/module.h>

#include "export_api.h "

static int __init export_chargement (void) {

printk(KERN_ALERT "Hello, world\n"); return 0;

}

static void __exit export_dechargement (void){

printk(KERN_ALERT "Goodbye, cruel world\n"); }

void fonction_hello (int numero) {

printk (KERN_INFO "Hello, le numero est %d\n", numero);}

EXPORT_SYMBOL(fonction_hello);

MODULE_LICENSE("GPL");

module_init(export_chargement);module_exit(export_dechargement);

drv_exportdrv_import

#include <linux/module.h>

#include "export_api.h "

static int __init import_chargement (void){

printk(KERN_ALERT "Hello, world\n");

fonction_hello (10);

return 0;}

static void __exit import_dechargement (void){

fonction_hello(20);

printk(KERN_ALERT "Goodbye, cruel world\n");}

MODULE_LICENSE("GPL");

module_init(import_chargement);module_exit(import_dechargement);

Page 51: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 51 /

Soit les fichiers suivant :

$ ls -altotal 28drwx------ 2 tgayet tgayet 4096 oct. 14 16:21 .drwx------ 6 tgayet tgayet 4096 oct. 14 16:06 ..-rw-r--r-- 1 tgayet tgayet 934 oct. 14 16:09 drv_export.c-rw-r--r-- 1 tgayet tgayet 384 oct. 14 16:09 drv_import.c-rw-r--r-- 1 tgayet tgayet 91 oct. 14 16:11 export_api.h-rw-r--r-- 1 tgayet tgayet 298 oct. 14 16:16 MakefileExport-rw-r--r-- 1 tgayet tgayet 298 oct. 14 16:16 MakefileImport

Créons un lien symbolique le makefile d'export :

$ ln -s MakefileExport Makefile

Compilons le module export son symbole :

$ make

filename: ./drv_export.kolicense: GPLsrcversion: 183B55C160FEE0392CEBDFFdepends: vermagic: 3.2.0-53-generic-pae SMP mod_unload modversions 686

$ cat Module.symvers0xb61f5663 fonction_hello /media/9DA1-2D6A/atelier/_symbol/drv_export EXPORT_SYMBOL

Pas de dépendancepour ce module

Page 52: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 52 /

Créons un lien symbolique le makefile d'import:

$ ln -s MakefileImport Makefile

Compilons le module important le symbole :

$ make

filename: ./drv_import.kolicense: GPLsrcversion: 5160DCAE26652416467A0FCdepends: drv_exportvermagic: 3.2.0-53-generic-pae SMP mod_unload modversions 686

Chargement du module important avant le module exportant :

$ sudo insmod ./drv_import.koinsmod: error inserting './drv_import.ko': -1 Unknown symbol in module

Chargeons le module exportant avant le changement du module important :

$ sudo insmod ./drv_export.ko$ sudo insmod ./drv_import.ko

Dépendance vers le moduledrv_export

Page 53: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 53 /

Visualisation du module exportant le symbole :

$ lsmod | grep drv_exportdrv_export 12556 1 drv_import

Visualisation du module important ainsi que son lien avec le module exportant le symbole :

$ lsmod | grep drv_importdrv_import 12402 0drv_export 12556 1 drv_import

Vérifions l'export du symbole dans le noyau :

$ cat /proc/kallsyms | grep fonction_hello00000000 r __ksymtab_fonction_hello [drv_export]00000000 r __kstrtab_fonction_hello [drv_export]00000000 r __kcrctab_fonction_hello [drv_export]00000000 T fonction_hello [drv_export]

Essayons de décharger le module drv_import avant le module drv_export :

$ sudo rmmod ./drv_export.koERROR: Module drv_export is in use by drv_import

Le déchargement doit aussi se faire en respectant les dépendances :

$ sudo rmmod ./drv_import.ko$ sudo rmmod ./drv_export.ko

drv_export utilisé 1 fois parle module drv_import

Page 54: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 54 /

Notion de type de drivers

→ Le but de cet atelier sera de comprendre les types de drivers

Répertoire : atelier/_typedriver/

Page 55: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 55 /

Linux spécifie plusieurs type de drivers :

- drivers de caractères

- drivers de blocks

- drivers réseau (sorte de drivers de blocks)

Page 56: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 56 /

Drivers de blocks :

$ ls -al /dev

(...)brw-rw---- 1 root disk 8, 0 oct. 1 17:29 sdabrw-rw---- 1 root disk 8, 1 oct. 1 17:29 sda1brw-rw---- 1 root disk 8, 2 oct. 1 17:29 sda2brw-rw---- 1 root disk 8, 16 oct. 1 17:29 sdbbrw-rw---- 1 root disk 8, 32 oct. 1 17:29 sdcbrw-rw---- 1 root disk 8, 48 oct. 1 17:29 sddbrw-rw---- 1 root disk 8, 64 oct. 1 17:29 sdebrw-rw---- 1 root disk 8, 80 oct. 14 11:04 sdfbrw-rw---- 1 root disk 1, 0 oct. 1 17:29 ram0brw-rw---- 1 root disk 1, 1 oct. 1 17:29 ram1brw-rw---- 1 root disk 1, 10 oct. 1 17:29 ram10brw-rw---- 1 root disk 1, 11 oct. 1 17:29 ram11(...)

b = block

Ces fichiers sont utilisés entre l'espace noyau et l'espace utilisateur pour communiquer.

Page 57: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 57 /

Drivers de caractères :

$ ls -al /dev

(...)crw-rw-rw- 1 root tty 5, 0 oct. 15 09:28 ttycrw--w---- 1 root tty 4, 0 oct. 1 17:29 tty0crw-rw---- 1 root tty 4, 1 oct. 1 17:29 tty1crw--w---- 1 root tty 4, 10 oct. 1 17:29 tty10crw--w---- 1 root tty 4, 11 oct. 1 17:29 tty11crw--w---- 1 root tty 4, 12 oct. 1 17:29 tty12crw--w---- 1 root tty 4, 13 oct. 1 17:29 tty13crw--w---- 1 root tty 4, 14 oct. 1 17:29 tty14crw--w---- 1 root tty 4, 15 oct. 1 17:29 tty15crw--w---- 1 root tty 4, 16 oct. 1 17:29 tty16crw--w---- 1 root tty 4, 17 oct. 1 17:29 tty17crw--w---- 1 root tty 4, 18 oct. 1 17:29 tty18crw--w---- 1 root tty 4, 19 oct. 1 17:29 tty19(...)

c = caractères

Page 58: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 58 /

https://www.kernel.org/doc/Documentation/devices.txt

Si l'on regarde la documentation Documentation/devices.txt des sources du noyau GNU/Linux:

Exemple avec le driver de caractères de major 1 :

1 char Memory devices1 = /dev/mem Physical memory access2 = /dev/kmem Kernel virtual memory access3 = /dev/null Null device4 = /dev/port I/O port access5 = /dev/zero Null byte source6 = /dev/core OBSOLETE - replaced by /proc/kcore7 = /dev/full Returns ENOSPC on write8 = /dev/random Nondeterministic random number gen.9 = /dev/urandom Faster, less secure random number gen.10 = /dev/aio Asynchronous I/O notification interface11 = /dev/kmsg Writes to this come out as printk's12 = /dev/oldmem Used by crashdump kernels to access

the memory of the kernel that crashed.

Numéromajor

Numérominor

Un driver de block ou de caractères est toujours associé à un couple major / minor.

Ex : le driver de numéro major 1 et de numéro minor 9 est associé à un générateur denombres aléatoires.

Page 59: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 59 /

Vérifiez la présence de /dev/urandom :

$ ls -al /dev/urandomcrw-rw-rw- 1 root root 1, 9 oct. 1 17:29 /dev/urandom

On peut vérifier son fonctionnement :

$ hexdump /dev/urandom

0000000 a41a f4ec 66ef 020b 041e c119 3055 e5610000010 ab7c 5818 5345 f7f6 d73f 6e10 d7e9 d2720000020 a84a 729e 395e 0fde b108 9a09 9f93 99fb0000030 11fd 2681 521c eb8d e938 6ec1 0ecf a5db0000040 c919 2fde db6d c1cf 597b 405c ce63 a39c0000050 f102 423d c2e2 61aa 79e5 eccf bc41 4cf50000060 65a3 78b2 b9a3 bd8d 4570 2cce 62ed 924d0000070 b2b5 69b0 6860 9c3c 4aff 5374 3994 506b0000080 c19b 94c4 23fa 2642 1043 caf9 6ec5 07ae0000090 a2b2 d929 e3da a3dd 9ca5 59f8 f3af dceb00000a0 f6e6 6a4c 1492 3bdf 598e d3d3 1c4e 602900000b0 078d 99c8 1018 b2e6 2a6b 58e6 e505 d79200000c0 3cae 192d 5e83 28e8 31cb c3d2 1cc0 d96100000d0 d6de 5c24 3a2e 73ab 5b06 4a84 cd3b cc1000000e0 c8bf 9a33 dcf5 da81 4ae3 1858 3c42 225200000f0 b3c5 4996 6366 a068 4c99 98cf bd44 0ff5(...)

Page 60: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 60 /

Recréons un fichier de node dans /dev avec le même major (1) / minor (9) :

$ sudo mknod /dev/alea c 1 9[sudo] password for tgayet:

$ ls -al /dev/aleacrw-r--r-- 1 root root 1, 9 oct. 15 10:35 /dev/alea

$ hexdump /dev/alea0000000 7d84 029a c67f a414 b40a 291b b4c5 6d6b0000010 a691 ff5b b804 d24c 57e3 8ea6 2422 668f0000020 4af5 b5ca 1a7f d651 7478 f174 cb21 8fb30000030 5684 ec9d d18c d294 2843 3056 2c34 377e0000040 5303 7cf0 50c7 61a4 0055 99a8 0729 38ed0000050 d971 7a53 aeed 670f c053 20c8 b07f c98a0000060 0876 7f84 cf0a fe4d 66e5 e2af e7be 1e620000070 3c13 b91f 211a 0e79 590a eb1d e7c8 22920000080 b887 f0d6 289e 986f b4f5 03da ed64 21c10000090 61b1 d4c1 3dd6 25e1 c975 3bf9 c415 521200000a0 efeb be65 201f f570 5d8c 2d7b f277 58a100000b0 bd81 f25e bc6c fd8c b096 31a0 5272 7f3c00000c0 300d e420 85c9 f022 5aec 894c cf65 504b00000d0 a039 effd a143 d611 f87e ae4a 07ac 768e00000e0 f8d2 cda3 67c1 df0f 94b6 4f7d 5f3d e7c7(…)

Les deux fichier /dev/urandom et notre /dev/alea ont le même rendu car ils pointent sur le même driver dans le noyau.

Page 61: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 61 /

Utilisation de /proc

→ Le but de cet atelier sera de comprendre comment utiliser /proc

Répertoire : atelier/_proc/

Page 62: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 62 /

#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/proc_fs.h>#include <linux/jiffies.h>#include <asm/uaccess.h>

#define MODULE_VERS "1.0"#define MODULE_NAME "procfs_example"#define FOOBAR_LEN 8

struct fb_data_t{

char name[FOOBAR_LEN+1];char value[FOOBAR_LEN+1];

};

// Spécifie le nom du répertorie principal dans /procchar procentry [] = { "eurogiciel" };

static struct proc_dir_entry *example_dir, *foo_file, *bar_file, *jiffies_file, *symlink;

struct fb_data_t foo_data, bar_data;

static int proc_read_jiffies (char *page, char **start, off_t off, int count, int *eof, void *data){

int len;

len = sprintf(page, "jiffies = %ld\n", jiffies);

return len;}

Page 63: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 63 /

Callback read only :

static int proc_read_foobar (char *page, char **start, off_t off, int count, int *eof, void *data){

int len;struct fb_data_t *fb_data = (struct fb_data_t *)data;

len = sprintf(page, "%s = '%s'\n", fb_data->name, fb_data->value);

return len;}

Callback read / write :

static int proc_write_foobar (struct file *file, const char *buffer, unsigned long count, void *data){

int len;struct fb_data_t *fb_data = (struct fb_data_t *)data;

if(count > FOOBAR_LEN)len = FOOBAR_LEN;

elselen = count;

if(copy_from_user(fb_data->value, buffer, len))return -EFAULT;

fb_data->value[len] = '\0';

return len;}

Page 64: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 64 /

Fonction de chargement :

static int __init init_procfs_example (void){

int rv = 0;

/* Création du répertoire « eurogiciel » dans /proc */example_dir = proc_mkdir (procentry, NULL);if (example_dir == NULL){

rv = -ENOMEM;goto out;

}

/* Création du fichier « jiffies » dans /proc/eurogiciel *//* nb : sera en « read only » uniquement */jiffies_file = create_proc_read_entry ( "jiffies" , 0444, example_dir , proc_read_jiffies , NULL );if (jiffies_file == NULL){

rv = -ENOMEM;goto no_jiffies;

}

/* Création du fichier « foo » dans /proc/eurogiciel */foo_file = create_proc_entry ( "foo" , 0644, example_dir );if (foo_file == NULL){

rv = -ENOMEM;goto no_foo;

}

Page 65: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 65 /

strcpy(foo_data.name, "foo");strcpy(foo_data.value, "foo");foo_file->data = &foo_data;foo_file->read_proc = proc_read_foobar ;foo_file->write_proc = proc_write_foobar ;

/* Création d'un fichier « bar » dans /proc/eurogiciel/bar */bar_file = create_proc_entry ( "bar" , 0644, example_dir );if (bar_file == NULL){

rv = -ENOMEM;goto no_bar;

}strcpy(bar_data.name, "bar");strcpy(bar_data.value, "bar");bar_file->data = &bar_data;bar_file->read_proc = proc_read_foobar ;bar_file->write_proc = proc_write_foobar ;

/* Création d'un lien symbolique de jiffies_too vers jiffies toujours dans /proc/eurogiciel */symlink = proc_symlink ( "jiffies_too" , example_dir , "jiffies" );if (symlink == NULL){

rv = -ENOMEM;goto no_symlink;

}

/* Affiche un message si okay */printk( KERN_INFO "%s %s initialised\n", MODULE_NAME, MODULE_VERS );return 0;

no_symlink:remove_proc_entry("bar" , example_dir );

no_bar:remove_proc_entry("foo" , example_dir );

no_foo:remove_proc_entry("jiffies" , example_dir );

no_jiffies:remove_proc_entry(procentry, NULL);

out:return rv;

}

Page 66: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 66 /

Fonction de déchargement :

static void __exit cleanup_procfs_example (void){

/* Suppression des fichier & repertoires */remove_proc_entry("jiffies_too", example_dir);remove_proc_entry("bar", example_dir);remove_proc_entry("foo", example_dir);remove_proc_entry("jiffies", example_dir);remove_proc_entry(procentry, NULL);

printk( KERN_INFO "%s %s removed\n", MODULE_NAME, MODULE_VERS );}

MODULE_AUTHOR("TG");MODULE_DESCRIPTION("procfs examples");MODULE_LICENSE("GPL");

module_init(init_procfs_example );module_exit(cleanup_procfs_example );

Page 67: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 67 /

Compilons le module et chargeons le :

$ make$ sudo insmod ./drv_proc.ko$ lsmod | grep procdrv_proc 12713 0

Vérifiions maintenant la nouvelle entrée dans le pseudo-filesystème /proc :

$ tree /proc/eurogiciel/

/proc/eurogiciel/├── bar├── foo├── jiffies└── jiffies_too -> jiffies

0 directories, 4 files

# ls -al /proc/eurogiciel/total 0dr-xr-xr-x 2 root root 0 oct. 15 11:51 .dr-xr-xr-x 388 root root 0 oct. 1 17:28 ..-rw-r--r-- 1 root root 0 oct. 15 11:51 bar-rw-r--r-- 1 root root 0 oct. 15 11:51 foo-r--r--r-- 1 root root 0 oct. 15 11:51 jiffieslrwxrwxrwx 1 root root 7 oct. 15 11:51 jiffies_too -> jiffies

Page 68: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 68 /

Consultez la valeur de l'entrée /proc/eurogiciel/foo :

$ cat /proc/eurogiciel/foofoo = 'foo'

foo est la valeur initiale de l'entrée.

Il est possible d'interagir avec l'entrée /proc/eurogiciel/foo :

$ su# echo "1" > /proc/eurogiciel/foo# cat /proc/eurogiciel/foofoo = '1'

On voit ici que la valeur a changé par rapport à sa valeur initiale.

La valeur poussé aux entrées dans /proc ou /sys doivent être prisent en compte en dynamique.

Page 69: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 69 /

Utilisation d'un driver de caractères

→ Le but de cet atelier sera de comprendre comment fonctionne un drivers de

caractères.

Répertoire : atelier/_caracteres/

Page 70: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 70 /

#include <linux/module.h>#include <linux/fs.h>#include <linux/cdev.h>#include <linux/slab.h>#include <asm/uaccess.h>

MODULE_DESCRIPTION("tp-char");MODULE_AUTHOR("TG");MODULE_LICENSE("GPL");

/* Arguments */static int major = 0; /* Major number */module_param(major, int, 0660);MODULE_PARM_DESC(major, "Static major number (none = dynamic)");

static size_t buf_size = 64; /* Buffer size */module_param(buf_size, int, 0660);MODULE_PARM_DESC(buf_size, "Buffer size");

/* Global variables */static char* buffer; /* Buffer interne */static size_t num = 0; /* Number of available bytes in the buffer */

static struct file_operations k_fops ={

.owner = THIS_MODULE,

.read = k_read,

.write = k_write,

.open = k_open,

.release = k_release,};

Structure de fonctions pour les callbacks

Page 71: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 71 /

static ssize_t k_read (struct file *file, char *buf, size_t count, loff_t *ppos){

size_t real;

real = min(num, count);

if (real)if (copy_to_user(buf, buffer, real))

return -EFAULT;

num = 0; /* Destructive read (no more data after a read) */

printk(KERN_DEBUG "char: read %d/%d chars\n", real, count);

return real;}

static ssize_t k_write (struct file *file, const char *buf, size_t count, loff_t *ppos){

size_t real;

real = min(buf_size, count);

if (real)if (copy_from_user(buffer, buf, real))

return -EFAULT;

num = real; /* Destructive write (overwrite previous data if any) */

printk(KERN_DEBUG "char: wrote %d/%d chars\n", real, count);

return real;}

Page 72: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 72 /

static int k_open (struct inode *inode, struct file *file){

printk(KERN_DEBUG "char: open()\n");

return 0;}

static int k_release (struct inode *inode, struct file *file){

printk(KERN_DEBUG "char: release()\n");

return 0;}

static void __exit k_exit (void){

kfree(buffer);

unregister_chrdev(major, "char");

printk(KERN_INFO "char: successfully unloaded\n");}

/** Module entry points*/module_init(k_init );module_exit(k_exit );

Page 73: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 73 /

static int __init k_init (void){

int ret;

ret = register_chrdev (major, "drv_char" , &k_fops );if (ret < 0) {

printk(KERN_WARNING "char: unable to get a major\n");

return ret;}

if (major == 0)major = ret; /* dynamic value */

buffer = (char *)kmalloc(buf_size, GFP_KERNEL);if (buffer != NULL) {

printk(KERN_DEBUG "char: allocated a %d bytes buffer\n", buf_size);} else {

printk(KERN_WARNING "char: unable to allocate a %d bytes buffer\n", buf_size);

unregister_chrdev(major, "char");

return -ENOMEM;}

printk(KERN_INFO "char: successfully loaded with major %d\n", major);

return 0;}

Page 74: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 74 /

Compilons le module dynamique :

$ make

filename: ./drv_char.kolicense: GPLauthor: TGdescription: tp-charsrcversion: CFC4D9D08EECAB190FE9801depends: vermagic: 3.2.0-53-generic-pae SMP mod_unload modversions 686parm: major:Static major number (none = dynamic) (int)parm: buf_size:Buffer size (int)

On remarquera les deux paramètres :

- major : numéro du numéro majeur- buf_size : taille du buffer interne

→ Un numéro majeur est associé à un driver donné, il lui est rattaché et unique

→ Un numéro mineur est associé à une instance de ce même driver (0, 1, 2, … )

Page 75: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 75 /

Chargement du module dynamique :

$ sudo insmod ./drv_char.ko

$ lsmod | grep drv_chardrv_char 12732 0

$ tree /sys/module/drv_char//sys/module/drv_char/├── holders├── initstate├── notes├── parameters│ ├── buf_size│ └── major├── refcnt├── sections│ ├── __mcount_loc│ └── __param├── srcversion└── uevent

Page 76: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 76 /

Allons récupérer le numéro majeur :

$ dmesg(...)[1188412.205152] char: allocated a 64 bytes buffer[1188412.205156] char: successfully loaded with major 249

$ cat /proc/devices | grep drv_char249 drv_char

Où « drv_char » est le nom du driver donné lors de son enregistrement.

Si l'on se reporte au fichier documentation/device.txt de la documentation du noyau GNU/Linux on peut se rattaché à un numéro

240-254 char LOCAL/EXPERIMENTAL USE240-254 block LOCAL/EXPERIMENTAL USE

Allocated for local/experimental use. For devices notassigned official numbers, these ranges should beused in order to avoid conflicting with future assignments.

Numéro majeur

Nom d'enregistrement du driver comme drivers de car actère

Page 77: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 77 /

Créons un device pour le drivers dans le répertoire /dev pour qu'il puisse communiquer avec l'espace

syntaxe : mknod : mknod <device> <b/c> MAJOR MINOR

Vérifions le device :

$ sudo mknod /dev/mychar c 249 0

$ ls -al /dev/mycharcrw-r--r-- 1 root root 249, 0 oct. 15 14:45 /dev/mychar

Résumé :/dev/mychar : fichier de périphérique (nom totalement arbitraire)c : spécifie le type de driver (ici caractères)249 : numéro major (associé au driver)0 : numéro minor (première instance)

Le drivers est désormais accessible depuis l'espace utilisateur via /dev/mychar

Page 78: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 78 /

Modifions les droits d'accès au drivers :

$ ls -al /dev/mycharcrw-r--r-- 1 root root 249, 0 oct. 15 14:45 /dev/mychar

$ sudo chmod u=rw,g=rw,o=rw /dev/mychar

$ ls -al /dev/mycharcrw-rw-rw- 1 root root 249, 0 oct. 15 14:45 /dev/mychar

Souvent un groupe est crée pour permettre son utilisation. C'est le cas du groupe /video pour /dev/video0 associé à V4L2.

Page 79: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 79 /

Vérifions que le buffer de notre module dynamique est bien vide :

$ cat /dev/mychar$ dmesg(...)[1197012.255214] char: open()[1197012.255231] char: read 0/32768 chars[1197012.255237] char: release()

Envoyons une chaîne de caractère au driver :

$ echo "test" > /dev/mychar$ dmesg(…)[1197218.194357] char: open()[1197218.194376] char: wrote 5/5 chars[1197218.194382] char: release()

Revérifions le buffer après le dernier push :

$ cat /dev/mychartest

$ cat /dev/mychar→ après avoir donné le contenu, le buffer du module dynamique est de nouveau vierge.

Page 80: Atelier noyau & drivers du 16/10/2013...15/09/2013 5 / Linux temps réel Ordonnancement dans le noyau standard Préemptif mais pas temps réel !! → du temps réel mou possible mais

15/09/2013 80 /