You are on page 1of 32

C.

Blaess

Solutions temps rel


sous Linux
2e dition

Pour concevoir un systme quilibr, stable et ractif aux vnements externes, il est indispensable de bien
comprendre le rle et lorganisation de ses divers composants. Cest lun des premiers buts de ce livre, qui dtaille
et commente les interactions, les activations et les commutations des tches. De trs nombreux exemples illustrant
le propos permettront au lecteur de raliser ses propres expriences sur son poste Linux.

Btir un systme temps rel sous contraintes temporelles fortes


Pour construire une application temps rel sous Linux, larchitecte logiciel doit choisir entre diffrentes solutions, un
choix crucial qui influera sensiblement sur les limites de fonctionnement de son application. Dans cet ouvrage, lauteur
tudie les environnements libres pouvant rpondre des contraintes temporelles plus ou moins fortes et propose
des outils pour valider le comportement des tches face des charges logicielles ou interruptives importantes.
Augmente et mise jour, la deuxime dition a pour support dexprimentation le nano-ordinateur Raspberry Pi.
Elle tudie galement la mise en uvre du temps rel sur la carte BeagleBone Black, de porte plus industrielle.

Au sommaire
Multitche et commutation Multitche sous Linux Systmes multiprocesseurs tats des tches Interruptions,
exceptions et appels systme Mode noyau Interruptions et exceptions Appels systme Threads du noyau
Ordonnancement temps partag et priorits Temps partag Configuration des priorits Limitations de lordonnancement
temps partag Mesure du temps Tches priodiques Premption des tches Principes du temps rel Traitement
direct dans le noyau Temps rel sous Linux Performances du temps rel souple Timers temps rel Temps de
commutation Premptibilit du noyau Problmes temps rel classiques Dmarrage en Round Robin Inversion de
priorit Prise de mutex Limites et amliorations du temps rel Linux Traitement des interruptions PREEMPT-RT
Outils de mesure des performances conomies dnergie Extensions temps rel de Linux Les nanokernels temps
rel Installation de Xenomai Expriences avec Xenomai Programmer avec Xenomai Programmation de tches
simples Alarmes et tches priodiques Synchronisation des tches Traitement des interruptions Programmation

Expert reconnu de Linux


dans lindustrie, Christophe
Blaess conoit et met
en uvre des systmes
embarqus industriels,
et propose au sein de la
socit Logilin quil a cre
en 2004 des prestations
dingnierie et de conseil
dans diffrents domaines
lis Linux. Soucieux de
partager ses connaissances
et son savoir-faire, il dispense
galement des formations
professionnelles (Linux temps
rel, Linux embarqu avec
Yocto, criture de drivers,
programmation systme),
co-organise des rencontres
ddies aux systmes
libres embarqus (Paris
Embedded Meetup) et publie
rgulirement des articles
sur son blog et dans des
revues spcialises.

dun driver Interruptions avec Xenomai.

qui sadresse cet ouvrage ?

Conception : Nord Compo

Sur le site http://christophe.blaess.fr


Tlchargez le code source des exemples
Consultez les corrigs des exercices et de nombreux documents complmentaires
Dialoguez avec lauteur

Code diteur : G14208


ISBN : 978-2-212-14208-2

Aux dveloppeurs, architectes logiciels et ingnieurs devant mettre en uvre des applications temps rel sous Linux
Aux dcideurs et industriels souhaitant installer un systme temps rel sous Linux
Aux tudiants en informatique

2e dition

Comprendre le fonctionnement de lordonnanceur et du noyau

C. Blaess

Solutions temps rel


sous Linux

Avec 50 exercices corrigs

Solutions
temps rel
sous Linux

2e dition

Cas pratique : le Raspberry Pi

Christophe Blaess

35

G14208_Temps_Reel_COUV_2e_04.indd Toutes les pages

06/11/15 14:13

C. Blaess

Solutions temps rel


sous Linux
2e dition

Pour concevoir un systme quilibr, stable et ractif aux vnements externes, il est indispensable de bien
comprendre le rle et lorganisation de ses divers composants. Cest lun des premiers buts de ce livre, qui dtaille
et commente les interactions, les activations et les commutations des tches. De trs nombreux exemples illustrant
le propos permettront au lecteur de raliser ses propres expriences sur son poste Linux.

Btir un systme temps rel sous contraintes temporelles fortes


Pour construire une application temps rel sous Linux, larchitecte logiciel doit choisir entre diffrentes solutions, un
choix crucial qui influera sensiblement sur les limites de fonctionnement de son application. Dans cet ouvrage, lauteur
tudie les environnements libres pouvant rpondre des contraintes temporelles plus ou moins fortes et propose
des outils pour valider le comportement des tches face des charges logicielles ou interruptives importantes.
Augmente et mise jour, la deuxime dition a pour support dexprimentation le nano-ordinateur Raspberry Pi.
Elle tudie galement la mise en uvre du temps rel sur la carte BeagleBone Black, de porte plus industrielle.

Au sommaire
Multitche et commutation Multitche sous Linux Systmes multiprocesseurs tats des tches Interruptions,
exceptions et appels systme Mode noyau Interruptions et exceptions Appels systme Threads du noyau
Ordonnancement temps partag et priorits Temps partag Configuration des priorits Limitations de lordonnancement
temps partag Mesure du temps Tches priodiques Premption des tches Principes du temps rel Traitement
direct dans le noyau Temps rel sous Linux Performances du temps rel souple Timers temps rel Temps de
commutation Premptibilit du noyau Problmes temps rel classiques Dmarrage en Round Robin Inversion de
priorit Prise de mutex Limites et amliorations du temps rel Linux Traitement des interruptions PREEMPT-RT
Outils de mesure des performances conomies dnergie Extensions temps rel de Linux Les nanokernels temps
rel Installation de Xenomai Expriences avec Xenomai Programmer avec Xenomai Programmation de tches
simples Alarmes et tches priodiques Synchronisation des tches Traitement des interruptions Programmation

dun driver Interruptions avec Xenomai.

qui sadresse cet ouvrage ?


Aux dveloppeurs, architectes logiciels et ingnieurs devant mettre en uvre des applications temps rel sous Linux
Aux dcideurs et industriels souhaitant installer un systme temps rel sous Linux
Aux tudiants en informatique

Sur le site http://christophe.blaess.fr


Tlchargez le code source des exemples
Consultez les corrigs des exercices et de nombreux documents complmentaires
Dialoguez avec lauteur

G14208_Temps_Reel_COUV_2e_04.indd Toutes les pages

Expert reconnu de Linux


dans lindustrie, Christophe
Blaess conoit et met
en uvre des systmes
embarqus industriels,
et propose au sein de la
socit Logilin quil a cre
en 2004 des prestations
dingnierie et de conseil
dans diffrents domaines
lis Linux. Soucieux de
partager ses connaissances
et son savoir-faire, il dispense
galement des formations
professionnelles (Linux temps
rel, Linux embarqu avec
Yocto, criture de drivers,
programmation systme),
co-organise des rencontres
ddies aux systmes
libres embarqus (Paris
Embedded Meetup) et publie
rgulirement des articles
sur son blog et dans des
revues spcialises.

2e dition

Comprendre le fonctionnement de lordonnanceur et du noyau

C. Blaess

Solutions temps rel


sous Linux

Avec 50 exercices corrigs

Solutions
temps rel
sous Linux

2e dition

Cas pratique : le Raspberry Pi

Christophe Blaess

06/11/15 14:13

Solutions
temps rel
sous Linux
2e dition

G00000_TempsReel-PDT_2e.indd 1

29/10/15 10:44

Dans la collection Les guides de formation Tsoft


J.-F. Bouchaudy. Linux Administration. Tome 1 : les bases de ladministration systme.
N14082, 3e dition, 2014, 690 pages.
J.-F. Bouchaudy. Linux Administration. Tome 2 : administration systme avance.
N12882, 2e dition, 2011, 504 pages.
J.-F. Bouchaudy. Linux Administration. Tome 3 : scuriser un serveur Linux.
N13462, 2e dition, 2012, 400 pages.
J.-F. Bouchaudy. Linux Administration. Tome 4 : installer et configurer des serveurs Web, mail ou FTP
sous Linux.
N13790, 2e dition, 2013, 420 pages.
Autres ouvrages
P. Ficheux. Linux embarqu.
N13482, 4e dition, 2012, 378 pages.
c. Blaess. Dveloppement systme sous Linux. Ordonnancement multitches, gestion mmoire,
communications, programmation rseau. paratre.
N14207, 4e dition, 2016, 1004 pages.
c. Blaess. Shells Linux et Unix par la pratique.
N13579, 2e dition, 2012, 296 pages.
i. hurBain, e. dreyFus. Mmento Unix/Linux
N13306, 2e dition, 2011, 14 pages.

Solutions
temps rel
sous Linux
2e dition

Christophe Blaess

G00000_TempsReel-PDT_2e.indd 2

29/10/15 10:44

DITIONS EYROLLES
61, bd Saint-Germain
75240 Paris Cedex 05
www.editions-eyrolles.com

En application de la loi du 11 mars 1957, il est interdit de reproduire intgralement ou partiellement le prsent ouvrage,
sur quelque support que ce soit, sans lautorisation de lditeur ou du Centre Franais dexploitation du droit de copie,
20, rue des Grands Augustins, 75006 Paris.
Groupe Eyrolles, 2012, 2016, ISBN : 978-2-212-14208-2

Table des matires


CHAPITRE 1

Multitche et commutation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Multitche sous Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Cration de processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Paralllisme multithreads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Systmes multiprocesseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Multiprocesseurs, multicurs et hyperthreading . . . . . . . . . . . . . . . . . . . . . . . 8
Affinit dune tche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
tats des tches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Ordonnancement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Premption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Points cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice1 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice2 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice3 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice4 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

21
21
21
22
22

CHAPITRE 2

Interruptions, exceptions et appels systme . . . . . . . . . . . . . . . . . . . . 23


Mode noyau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Interruptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Entres-sorties sans interruptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

Blaess.indb 7

22/10/2015 14:15

VIII

Solutions temps rel sous Linux

Entres-sorties avec interruptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26


Interruptions sous Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Routage des interruptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Fichier core . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Appels systme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Suivi dun appel systme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Threads du noyau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Points cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice1 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice2 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice3 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice4 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice5 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39
39
39
39
40
40

CHAPITRE 3

Ordonnancement temps partag et priorits . . . . . . . . . . . . . . . . . . . . 41


Temps partag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Principes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ordonnanceur historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ordonnanceurs du noyau2.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ordonnanceur CFS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Groupes de processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Autres ordonnanceurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41
41
44
45
46
47
51

Configuration des priorits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51


Courtoisie des processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Priorits entre threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Points cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Exercice1 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Exercice2 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

Blaess.indb 8

22/10/2015 14:15

Table des matires

IX

Exercice3 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56


Exercice4 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Exercice5 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
CHAPITRE 4

Limitations
delordonnancement temps partag . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Mesure du temps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Heure Unix avec gettimeofday() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Prcision des mesures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Horloges Posix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

57
58
58
61

Tches priodiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Timers Unix classiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Timers Posix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Granularit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Prcision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

64
64
66
68
70

Premption des tches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79


Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Points cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice1 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice2 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice3 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice4 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice5 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

83
83
83
83
83
84

CHAPITRE 5

Principes du temps rel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85


Dfinitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Temps rel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Classes de temps rel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Temps rel absolu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Temps rel strict . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Temps rel strict certifiable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Temps rel strict non certifiable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

TOC_blaess.indd 9

85
85
86
86
87
87
88

28/10/2015 10:19

Solutions temps rel sous Linux

Temps rel souple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88


Rles respectifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

Traitement direct dans le noyau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90


Traitement des interruptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Temps rel sous Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
chelle des priorits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Configuration de lordonnancement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Processus temps rel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Garde-fou temps rel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Threads temps rel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Threads en Round Robin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Rotation sans Round Robin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Temps rel depuis le shell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ordonnancement EDF (Earliest Deadline First) . . . . . . . . . . . . . . . . . . . . . . .

94
94
96
98
100
101
106
109
110
111

Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Points cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice1 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice2 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice3 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice4 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice5 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

118
118
118
118
118
118

CHAPITRE 6

Performances dutempsrel souple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

Blaess.indb 10

Timers temps rel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


Prcisions et fluctuations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Granularit des timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Conclusion sur les timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

119
119
122
122

Temps de commutation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Commutation entre threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Commutations entre processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Comparaison processus et threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Imprvisibilits dues la mmoire virtuelle . . . . . . . . . . . . . . . . . . . . . . . . . . .

123
123
127
128
130

22/10/2015 14:15

Table des matires

Premptibilit du noyau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Principes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Premptibilit du noyau standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Connatre la configuration dun noyau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Expriences sur la premptibilit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

XI

132
132
134
135
136

Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Points cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice1 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice2 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice3 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice4 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice5 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

145
145
145
145
145
146

CHAPITRE 7

Problmes temps rel classiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147


Dmarrage en Round Robin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
Barrires Posix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Inversion de priorit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
Hritage de priorit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Prise de mutex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Comportement en temps rel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Reprise de mutex en temps rel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Appel explicite lordonnanceur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

156
159
162
165
167
168

Points cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169


Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice1 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice2 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice3 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice4 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice5 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

TOC_blaess.indd 11

169
169
169
169
169
169

28/10/2015 10:19

XII

Solutions temps rel sous Linux

CHAPITRE 8

Limites et amliorations dutemps rel Linux . . . . . . . . . . . . . . . . . . . 171


Traitement des interruptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
PREEMPT_RT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Threaded interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Fully preemptible kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Conclusion sur PREEMPT_RT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

178
181
183
183

Outils de mesure des performances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184


Cyclictest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Hwlatdetect, Hackbench... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
conomies dnergie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Variation de frquence dhorloge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Heuristique performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Heuristique powersave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Heuristique ondemand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

186
187
189
190
190

Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
Points cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice1 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice2 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice3 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice4 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice5 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

192
192
192
192
192
192

CHAPITRE 9

Extensions temps rel de Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193


Les nanokernels temps rel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Principes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
RTLinux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
RTAI et Adeos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Xenomai . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Interface de programmation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

193
193
195
195
198
200

Installation de Xenomai . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201


Modification du noyau Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201

Blaess.indb 12

22/10/2015 14:15

Table des matires

XIII

Compilation de Linux modifi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203


Compilation de Xenomai . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205

Expriences avec Xenomai . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206


Premire exploration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
Programmes de tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
Points cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice1 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice2 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice3 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice4 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

211
211
211
212
212

CHAPITRE 10

Programmer avec Xenomai . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213


Programmation de tches simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Principes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Initialisation du processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Cration de tche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Compilation et excution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Processus unithread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Recherche des changements de modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

213
213
215
216
218
220
221

Alarmes et tches priodiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


Rveils priodiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Alarmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Watchdog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

223
223
232
235

Synchronisation des tches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237


Smaphores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
Mutex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
Points cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
Exercice1 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
Exercice2 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246

Blaess.indb 13

22/10/2015 14:15

XIV

Solutions temps rel sous Linux

Exercice3 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246


Exercice4 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
CHAPITRE 11

Traitement des interruptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247


Programmation dun driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Squelette dun module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Structure dun driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Traitement des interruptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Traitement en threaded interrupt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

247
247
249
255
261

Interruptions avec Xenomai . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265


Real Time Driver Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
Interruptions avec RTDM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
Points cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice1 (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice2 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice3 (**) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exercice4 (***) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

276
276
276
276
276

Conclusion

tat des lieux et perspectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277


Situation actuelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Linux vanilla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Patch PREEMPT_RT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Xenomai . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Mesures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

277
277
278
278
278

Perspectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
ANNEXEA

Compilation dun noyau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281


Prparation des sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Configuration de la compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
Principes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283

Blaess.indb 14

22/10/2015 14:15

Table des matires

XV

Interfaces utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285


Options de compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286

Compilation et installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287


Compilation croise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
Compilation native . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
ANNEXE B

Bibliographie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
Livres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
Articles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
Sites web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295

Blaess.indb 15

22/10/2015 14:15

Blaess.indb 16

22/10/2015 14:15

1
Multitche et commutation
Lordonnancement sous Linux est avant tout une affaire de gestion des tches en attente. Sur
un poste de travail courant, il tourne en permanence une bonne centaine de processus, dont
la plupart sont endormis, en attente dvnements extrieurs (actions de lutilisateur, donnes
provenant du rseau, etc.), et quelques-uns seulement sont actifs un moment donn. Dans ce
chapitre, nous allons examiner la reprsentation et ltat des tches, ainsi que la notion dordonnancement premptif.

Multitche sous Linux


Le fonctionnement multitche sexprime traditionnellement sur les systmes Unix sous forme
de processus. Pourtant, lordonnancement nest que trs faiblement concern par les processus,
et repose en ralit sur la notion de threads. Un processus correspond plus exactement un
espace indpendant de mmoire virtuelle, dans lequel un ou plusieurs threads sexcutent. La
notion de threads, notamment leur normalisation par le standard Posix, est relativement rcente
(annes1990) dans lhistoire des systmes Unix.
Sur la figure1-1, nous voyons que la commutation entre les threads est gre par lordonnanceur
(scheduler) tandis que la gestion des espaces de mmoire virtuelle des processus est assure par
le gestionnaire de mmoire MM (Memory Manager) du noyau. Nous pouvons remarquer que le
processusP3 ne comporte quun seul thread, cest le cas de nombreuses applications classiques
sous Linux.

Blaess.indb 1

22/10/2015 14:15

Solutions temps rel sous Linux

Figure1-1

Processus et threads

On peut noter galement sur cette figure une frontire entre lespace utilisateur celui dans
lequel sexcutent toutes les applications, et lespace noyau. Cette frontire est trs importante
et repose sur une transition du mode de fonctionnement du processeur. Linux sexcute sur des
microprocesseurs qui disposent dau moins deux modes de fonctionnement.
Un mode privilgi, dans lequel le processeur peut excuter nimporte quelle opration de
son jeu dinstructions dfini par le constructeur. Il peut galement y raliser des entressorties directes vers les priphriques matriels externes. Enfin, il lui est possible de modifier
la configuration de la mmoire virtuelle travers le composant MMU (dont nous reparlerons
plus loin).
Un mode restreint, dans lequel le processeur est limit un sous-ensemble de son jeu dinstructions. Dans ce cas, il ne peut accder qu certaines oprations dentres-sorties et
certaines plages de mmoire virtuelle qui ont t explicitement configures depuis le mode
privilgi.
Le code du noyau sexcute toujours en mode privilgi, celui des applications (mme celles qui
disposent des droits de ladministrateur root) uniquement en mode restreint. Ainsi, un processus
en mode utilisateur ne pourra ni accder indment au matriel, ni toucher des pages de mmoire
qui ne lui auraient t volontairement et explicitement accordes par le noyau. Toute tentative de
violer ces limites (par exemple, en essayant dexcuter une instruction assembleur rserve au
mode privilgi ou en accdant une page mmoire non attribue) se solderait immdiatement
par la leve dune exception, cest--dire une interruption interne aussi appele une trappe
sur certains systmes dexploitation qui rendrait immdiatement le contrle au noyau afin quil
prenne des dispositions adquates (comme tuer le processus coupable ou au contraire lui attribuer les ressources demandes).
Lorsquun processus sexcutant en mode utilisateur dsire obtenir un accs un priphrique
matriel, par exemple, il devra demander au noyau de raliser pour lui les oprations voulues
(lecture, criture, paramtrage, projection en mmoire...) en invoquant un appel systme.
Ces appels systme sont des routines dassistance, o le processus utilisateur sous-traite au
noyau certaines oprations ncessitant des privilges. Avant de raliser le travail demand, ce
dernier vrifiera que le processus dispose bien de toutes les autorisations adquates.

Blaess.indb 2

22/10/2015 14:15

Multitche et commutation
Chapitre 1

Cration de processus
La cration dun nouveau processus seffectue via lappel systme fork(). Celui-ci duplique
le processus appelant (traditionnellement appel pre) pour crer un nouveau processus
(fils). Les deux processus continuent leurs progressions en parallle partir du point de retour
de fork(). Le programme excut est le mme dans les deux processus, mais leur comportement
peut sappuyer sur le code de retour de fork() afin de raliser des oprations diffrentes. Dans le
processus pre, fork() renvoie le PID (Process IDentifier) du fils nouvellement cr, tandis que
dans le fils, fork() renvoie toujours zro.
pid_t fork (void);

La fin du processus survient lors dun appel exit() ou le retour de la fonction main() ou si le
processus reoit un signal fatal quil ne traite pas. Le processus pre peut attendre la fin de son
fils en invoquant waitpid(). Cet appel systme lui permet de connatre, par lintermdiaire dune
variable entire, les conditions de terminaison de son fils (a-t-il appel exit()? si oui, avec quel
argument? sinon, a-t-il t tu par un signal? lequel? etc.).
void exit (int status);
pid_t waitpid (pid_t fils, int * status, int options);

Enfin, un processus peut charger dans sa mmoire un nouveau code excutable, abandonnant
totalement son programme prcdent pour commencer le droulement dune nouvelle fonction
main(). Ceci seffectue avec lune des fonctions de la famille exec(), dont seul execve() est
rellement un appel systme, les autres tant des fonctions de bibliothques qui arrangent leurs
arguments avant de linvoquer.
int

int
int

int
int
int

execve (const char *fichier,


char *const envp[]);
execl (const char *fichier,
execle (const char *fichier,
char * const envp[]);
execlp (const char *fichier,
execv (const char *fichier,
execvp (const char *fichier,

char *const argv[],


const char *arg,...);
const char *arg, ...,
const char *arg, ...);
char *const argv[]);
char *const argv[]);

Avec cet ensemble de primitives systme fork(), execve(), exit(), waitpid() , on peut
organiser tout le multitche classique Unix fond sur des processus. Bien sr, des fonctions
de bibliothques comme system() ou posix_spawn() simplifient le travail du programmeur en
encadrant ces appels systme et rendent plus ais le dmarrage dun nouveau processus.
Voici un petit programme qui se prsente comme un shell (trs) minimal, il lit des lignes de
commandes et les fait excuter par un processus fils.
exemple-processus:
#include
#include
#include
#include
#include

Blaess.indb 3

<stdio.h>
<stdlib.h>
<string.h>
<unistd.h>
<sys/wait.h>

22/10/2015 14:15

Solutions temps rel sous Linux

#define LG_LIGNE 256


int main(void)
{
char ligne[LG_LIGNE];
while(1) {
// Afficher un symbole d'invite (prompt)
fprintf(stderr, "--> ");
// Lire une ligne de commandes
if (fgets(ligne, LG_LIGNE, stdin) == NULL)
break;
// Supprimer le retour chariot final
ligne[strlen(ligne)-1] = \0';
// Lancer un processus
if (fork() == 0) {
// --- PROCESSUS FILS --// Excuter la commande

execlp(ligne, ligne, NULL);


// Message d'erreur si on choue
perror(ligne);

exit(EXIT_FAILURE);
} else {
// --- PROCESSUS PRE --// Attendre la fin de son fils

waitpid(-1, NULL, 0);


// Et reprendre la boucle
}
}
fprintf(stderr, "\n");
return EXIT_SUCCESS;
}

Lors de son excution, on peut lui faire raliser quelques commandes simples:
$ ./exemple-processus
--> ls
exemple-processus exemple-processus.c Makefile
--> date
dim. mars 27 22:29:06 CEST 2011
--> who
cpb
tty1
2011-03-27 19:12 (:0)
cpb
pts/0
2011-03-27 21:52 (:0.0)
cpb
pts/1
2011-03-27 21:56 (:0.0)
-->

Blaess.indb 4

22/10/2015 14:15

Multitche et commutation
Chapitre 1

Toutefois, ds que lon essaie de passer des arguments sur la ligne de commandes, la fonction
execlp() recherche un fichier excutable du nom complet (y compris les espaces et arguments)
et choue:
--> ls -l
ls -l: No such file or directory
--> (Contrle-D)
$

Si lon souhaitait crire un vrai interprteur de commandes, il faudrait analyser la ligne saisie,
dcouper les mots, etc. Ce petit programme est toutefois intressant dans sa gestion des primitives de base du multitche Unix. Ce sont les seules dont on disposait de manire standard
jusque dans les annes1990 environ.

Paralllisme multithreads
Au cours des annes1980, plusieurs implmentations ont t proposes pour obtenir un mcanisme multitche lger, fonctionnant lintrieur de lespace mmoire dun processus. Certaines
sappuyaient sur une commutation entre tches organises au sein mme du processus par une
bibliothque, tandis que dautres rclamaient une extension des primitives Unix classiques
pour permettre plusieurs tches de partager le mme espace mmoire. Dans les annes1990,
une volont duniformisation de lAPI des systmes Unix a donn naissance la norme Posix,
dont une section (Posix.1c) tait consacre aux threads. Cette srie de fonctions permet de grer
des Posix Threads, aussi appels Pthreads.
La cration dun nouveau thread sobtient en appelant pthread_create() qui on indique la fonction sur laquelle le thread nouvellement cr devra dmarrer. Lidentifiant du thread (de type
pthread_t) sera renseign durant cet appel. On peut galement prciser des attributs spcifiques
pour le thread et un argument pour la fonction excuter. Nous verrons ultrieurement des attributs (enregistrs dans lobjet pthread_attr_t); pour le moment nous nous contenterons de passer
un pointeur NULL en second argument de pthread_create().
int pthread_create (pthread_t * thread,
pthread_attr_t * attr,
void * (*fonction) (void *),
void * argument);

Ds que la fonction pthread_create() se termine avec succs, nous savons quun nouveau fil
dexcution se droule dans notre processus.
La fin de ce thread se produira lorsquil invoquera pthread_exit() ou terminera sa fonction principale par un return, en renvoyant un pointeur (ventuellement NULL sil na rien de particulier
retourner).
void pthread_exit (void * valeur);

Blaess.indb 5

22/10/2015 14:15

Solutions temps rel sous Linux

Le pointeur renvoy lors de la terminaison peut tre rcupr par nimporte quel autre thread qui
invoque pthread_join().
int pthread_join (pthread_t thread, void ** valeur);

Dans lexemple suivant, le thread main() de notre programme va dmarrer autant de nouveaux
threads quon lui a pass darguments sur sa ligne de commandes. Chacun dentre eux recevra
en paramtre de sa fonction principale un nombre (pass travers un cast dans un pointeur).
Chaque thread calculera alors la factorielle de son nombre en effectuant des boucles et en nous
affichant sa progression. Le rsultat du calcul sera renvoy la fin de la fonction du thread, et
rcupr dans le thread main(). Lintrt de ce programme est dutiliser les diffrentes primitives
que nous avons prsentes prcdemment.
exemple-threads.c:
#include
#include
#include
#include

<pthread.h>
<stdio.h>
<stdlib.h>
<unistd.h>

void * factorielle(void * arg)


{
int i;
long n = (long) arg;
long resultat = 1;
for (i = 2; i <= n; i ++) {
resultat = resultat * i;
fprintf(stderr, "%ld! : en calcul...\n", n);
sleep(1);
}
return (void *) resultat;
}
int main(int argc, char * argv[])
{
pthread_t * threads = NULL;
void * retour;
int i;
long n;
// Vrification des arguments
if (argc < 2) {
fprintf(stderr, "usage: %s valeurs..\n", argv[0]);
exit(EXIT_FAILURE);
}
// Allocation d'un tableau d'identifiants
threads = calloc(argc-1, sizeof(pthread_t));
if (threads == NULL) {
perror("calloc");
exit(EXIT_FAILURE);
}

Blaess.indb 6

22/10/2015 14:15

Multitche et commutation
Chapitre 1

fprintf(stderr, "main(): lancement des threads\n");


for (i = 1; i < argc; i ++) {
// Rcupration de l'argument numrique
if (sscanf(argv[i], "%ld", & n) != 1) {
fprintf(stderr, "%s: invalide\n", argv[i]);
exit(EXIT_FAILURE);
}
// Lancement du thread
if (pthread_create(& (threads[i-1]), NULL,
factorielle, (void *) n) != 0) {
fprintf(stderr,
"Impossible de demarrer le thread %d\n", i);
exit(EXIT_FAILURE);
}
}
fprintf(stderr, "main(): tous threads lances\n");
for (i = 1; i < argc; i ++) {
// Attente du thread
pthread_join(threads[i-1], & retour);
fprintf(stderr, "main(): %s! = %ld\n",
argv[i], (long) retour);
}
fprintf(stderr, "main(): tous threads termines\n");
free(threads);
return EXIT_SUCCESS;
}

Voici un petit exemple dexcution:


$ ./exemple-threads 3 5 7
main(): lancement des threads
main(): tous threads lances
7! : en calcul...
5! : en calcul...
3! : en calcul...
7! : en calcul...
5! : en calcul...
main(): 3! = 6
7! : en calcul...
5! : en calcul...
7! : en calcul...
main(): 5! = 120
7! : en calcul...
main(): 7! = 5040
main(): tous threads termines
$

Blaess.indb 7

22/10/2015 14:15

Solutions temps rel sous Linux

Systmes multiprocesseurs
Multiprocesseurs, multicurs et hyperthreading
Une part importante (et croissante) des ordinateurs actuels offre un degr plus ou moins avanc
de paralllisation physique des traitements. cet gard, le noyau Linux considre quil existe
deux types de systmes: les machines uniprocesseur sur lesquelles un seul fil dexcution est
prsent un moment donn, et les machines multiprocesseurs symtriques (SMP) qui permettent lexcution parallle de plusieurs tches. Ceci regroupe les plates-formes:
multiprocesseurs contenant rellement plusieurs processeurs physiques distincts;
multicurs: un seul processeur est prsent, mais il dispose de plusieurs dcodeurs dinstructions travaillant en parallle;
hyperthreading1: un seul processeur assure une commutation entre deux squences dinstructions diffrentes.
On retrouve bien sr des combinaisons de ces diffrentes possibilits. Ainsi, une machine
disposant de deux processeurs physiques diffrents, chacun deux comportant deux curs et
chaque cur tant hyperthread, donne lutilisateur la sensation de disposer de huit processeurs
virtuels diffrents.
Pour connatre les caractristiques du processeur, telles quelles ont t dtectes par le noyau
Linux, on peut interroger le pseudo-fichier /proc/cpuinfo. Voici un exemple sur un processeur
Intel quatre curs:
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model
: 58
model name : Intel(R) Core (TM) i3-3100M CPU @ 2.40 GHz
stepping
: 9
cpu MHz
: 1273.406
cache size : 3072 KB
physical id : 0
siblings
: 4
core id
: 0
cpu cores : 2
[...]
processor : 1
[...]
processor : 2
[...]
processor : 3
1. Le mot hyperthreading correspond une implmentation particulire (celle dIntel) dun
concept plus gnral nomm Simultaneous Multi Threading. Je prfre nanmoins conserver ce
terme car il est beaucoup plus rpandu.

Blaess.indb 8

22/10/2015 14:15

Multitche et commutation
Chapitre 1

vendor_id
cpu family
model
model name
stepping
cpu MHz
cache size
physical id
siblings
core id
cpu cores
[]
$

:
:
:
:
:
:
:
:
:
:
:

GenuineIntel
6
58
Intel(R) Core(TM) i3-3110M CPU @ 2.40GHz
9
1200.093
3072 KB
0
4
1
2

Nous voyons que nous disposons de quatre processeurs virtuels (lignes processor: 0 processor: 3). Toutefois, il sagit du mme processeur physique (lignes physical id: 0 identiques)
qui contient deux curs distincts (lignes core id : 0 et core id : 1). Chacun des curs est
hyperthread. On peut remarquer que la frquence CPU est diffrente sur des deux curs affichs, en effet sur de nombreux processeurs cette frquence est modifiable dynamiquement. Ici,
le noyau Linux la fait voluer en fonction de la charge du systme. Nous reviendrons sur ce sujet
dans le chapitre 8.
La commande lscpu, disponible sur de nombreux systmes Linux, prsente de manire plus
lisible le contenu de /proc/cpuinfo:
$ lscpu
Architecture:
x86_64
Mode(s) opratoire(s) des processeurs: 32-bit, 64-bit
Byte Order:
Little Endian
CPU(s):
4
On-line CPU(s) list:
0-3
Thread(s) par cur:
2
Cur(s) par socket:
2
Socket(s):
1
Nud(s) NUMA:
1
Identifiant constructeur: GenuineIntel
Famille de processeur: 6
Modle:
58
Rvision:
9
Vitesse du processeur en MHz: 1199.906
BogoMIPS:
4789.00
Virtualisation:
VT-x
Cache L1d:
32K
Cache L1i:
32K
Cache L2:
256K
Cache L3:
3072K
NUMA node0 CPU(s):
0-3
$

Blaess.indb 9

22/10/2015 14:15

10

Solutions temps rel sous Linux

Parfois lscpu est moins volubile, en voici un exemple dexcution sur Raspberry Pi 2:
$ lscpu
Architecture:
Byte Order:
CPU(s):
On-line CPU(s) list:
Thread(s) per core:
Core(s) per socket:
Socket(s):
$

armv7l
Little Endian
4
0-3
1
4
1

Au sein dune application, il est possible dappeler la fonction:


#include <unistd.h>
long sysconf (int nom);

Toutefois, avec largument _SC_NPROCESSORS_ONLN, il est important de savoir que cette fonctionnalit nest pas normalise et ne fonctionnera peut-tre que sous Linux. En voici un exemple:
exemple-sysconf.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
printf("Nombre de CPU: %ld\n",

sysconf(_SC_NPROCESSORS_ONLN));
return EXIT_SUCCESS;
}

Qui nous donne:


$ ./exemple-sysconf
Nombre de CPU: 4
$

Affinit dune tche


Lordonnanceur de Linux est capable de placer (et de dplacer) des tches sur les processeurs
virtuels du systme.
Comme reprsent sur la figure1-2, nous lanons une boucle infinie et active (consommatrice de temps CPU) depuis un shell. Lutilitaire GkrellM (Gnome Krell Monitor) que je
recommande vivement prsent droite de la fentre affiche graphiquement les activits des
quatre curs du processeur, mises jour toutes les secondes. Nous voyons que toute la charge
lie la boucle active est dabord porte par le cur0, puis lordonnanceur dcide de migrer
la tche (pour rpartir la charge globale sur les processeurs disponibles) vers le cur2. On

Blaess.indb 10

22/10/2015 14:15

Multitche et commutation
Chapitre 1

11

remarque un bref passage sur le cur 1 pendant quelques secondes et un retour prolong sur
lecur 2.
Figure1-2

Migration de tches

Cette migration intervient dynamiquement et spontanment, sans que le processus concern ne


sen rende compte.
Nous pouvons vrifier tout moment le processeur sur lequel sexcute une tche avec la fonction (spcifique GNU):
int sched_getcpu (void);

qui nous renvoie le numro de processeur depuis lequel elle a t invoque, ou -1 si elle ne peut
le dterminer.
Le petit programme suivant va vrifier en permanence son emplacement et nous indiquer
lorsquil dtectera des migrations:
exemple-sched-getcpu.c:
#define _GNU_SOURCE // sched_getcpu() extension GNU
#include
#include
#include
#include
#include

<sched.h>
<stdio.h>
<stdlib.h>
<time.h>
<unistd.h>

int main(void)
{
int n;
int precedent = -1;
time_t heure;
struct tm * tm_heure;

Blaess.indb 11

22/10/2015 14:15

12

Solutions temps rel sous Linux

while (1) {

n=sched_getcpu();
if (n == -1) {
perror("sched_getcpu");
exit(EXIT_FAILURE);
}
if (precedent == -1)
precedent = n;
if (n != precedent) {
heure = time(NULL);
tm_heure = localtime(& heure);
print("%02d:%02d:%02d migration %d -> %d\n",
tm_heure->tm_hour, tm_heure->tm_min,
tm_heure->tm_sec,
precedent, n);
precedent = n;
}
}
return EXIT_SUCCESS;
}

Nous voyons que le noyau dplace le processus alternativement sur les quatre curs en fonction
de la charge du systme.
$ ./exemple-sched-getcpu

08:29:40 migration
08:30:01 migration
08:30:07 migration
08:30:12 migration
08:30:12 migration
08:30:15 migration
08:30:21 migration
(Contrle-C)

3
0
2
0
1
2
3

->
->
->
->
->
->
->

0
2
0
1
2
3
0

Il nous est galement possible de contrler lemplacement dun processus, avant son lancement
ou pendant son excution. Pour cela, la commande shell taskset est trs utile. Toutefois, son
utilisation nest pas vraiment intuitive. En voici quelques exemples:
$ taskset -c 1 ./commande
// Lance la commande sur le CPU1
$ taskset 0,2 ./commande
// Autorise la commande sexcuter sur les CPU0 et 2
$ taskset -pc 0 1234
// Migre le processus1234 sur le CPU0
$ taskset -p 1234
// Affiche laffinit du processus1234

Blaess.indb 12

22/10/2015 14:15

Multitche et commutation
Chapitre 1

13

Laffinit dune tche est la liste des CPU sur lesquels elle peut sexcuter. On peut la consulter
ou la fixer laide des fonctions suivantes:
int sched_setaffinity (pid_t
pid,
size_t
taille,
const cpu_set_t * cpuset);
int sched_getaffinity (pid_t
pid,
size_t
taille,
cpu_set_t * cpuset);

Ces fonctions sont des extensions GNU non portables sur dautres systmes Unix qui ncessitent donc de dfinir la constante symbolique _GNU_SOURCE avant dinclure <sched.h>.
Le second argument de ces fonctions correspond la taille du type de donne cpu_set_t pour
le systme.
Les listes de CPU sont reprsentes par les variables de type cpu_set_t, que lon manipule avec
les fonctions suivantes:
void
void
void
int

CPU_ZERO
CPU_SET
CPU_CLR
CPU_ISSET

(cpu_set_t * ensemble);
(int cpu, cpu_set_t * ensemble);
(int cpu, cpu_set_t * ensemble);
(int cpu, cpu_set_t * ensemble);

La fonction CPU_ZERO() permet de vider un ensemble, CPU_SET() et CPU_CLR() permettent respectivement dinsrer ou de retirer un CPU dun ensemble, enfin CPU_ISSET() permet de vrifier si
un CPU est mentionn dans un ensemble ou non.
Voici un petit exemple daccrochage dun processus sur un CPU donn en argument. On notera
que la valeur0 en premier argument de sched_setaffiny() indique que lon fixe le masque daffinit pour le processus appelant.
exemple-sched-setaffinity.c:
#define _GNU_SOURCE
#include
#include
#include
#include

<stdio.h>
<stdlib.h>
<unistd.h>
<sched.h>

int main(int argc, char *argv[])


{
cpu_set_t cpuset;
int cpu;
// Lire le numro de CPU dans le premier argument
if ((argc != 2) || (sscanf(argv[1],"%d", &cpu)!=1)) {
fprintf(stderr, "usage: %s cpu\n", argv[0]);
exit(EXIT_FAILURE);
}
// Remplir l'ensemble avec le CPU indique

Blaess.indb 13

22/10/2015 14:15

14

Solutions temps rel sous Linux

CPU_ZERO(& cpuset);
CPU_SET(cpu, &cpuset);
// Fixer l'affinit
if (sched_setaffinity(0, sizeof(cpuset), &cpuset)!=0){
perror(argv[1]);
exit(EXIT_FAILURE);
}
while (1) {
printf("Je suis sur le CPU %d\n", sched_getcpu());
sleep(1);
}
return EXIT_SUCCESS;
}

Quelques exemples dexcution, sur un systme quatre curs:


$ ./exemple-sched-setaffinity 0
Je suis sur le CPU 0
Je suis sur le CPU 0
Je suis sur le CPU 0
Je suis sur le CPU 0

Contrle-C
$ ./exemple-sched-setaffinity 3
Je
Je
Je
Je

suis
suis
suis
suis

sur
sur
sur
sur

le
le
le
le

CPU
CPU
CPU
CPU

3
3
3
3

Contrle-C
$ ./exemple-sched-setaffinity 4
4: Invalid argument
$

On remarque que sched-setaffinity() choue si le numro de CPU est invalide.


Il est galement possible de fixer laffinit dun thread dans un processus. On peut ainsi tirer
parti du paralllisme physique du systme au sein dune application.
Ces fonctions ne sont pas dcrites dans la norme Pthreads (Posix.1c), aussi leur ajoute-t-on le
suffixe _np (non Posix) pour indiquer leur manque de portabilit. On peut fixer et lire laffinit dun thread dynamiquement avec:
int pthread_setaffinity_np (pthread_t
thread,
size_t
taille,
const cpu_set_t * cpuset);
int pthread_getaffinity_np (pthread_t thread,
size_t
taille,
cpu_set_t * cpuset);

Blaess.indb 14

22/10/2015 14:15

Multitche et commutation
Chapitre 1

15

On peut aussi fixer laffinit dun futur thread avant sa cration. Pour cela, on initialise un objet
pthread_attr_t qui contient les attributs du thread crer et on passe cette structure en second
argument de pthread_create().
Pour remplir la structure dattributs, on utilise les fonctions:
int pthread_attr_setaffinity_np (
pthread_attr_t
size_t
const cpu_set_t
int pthread_attr_getaffinity_np (
pthread_attr_t
size_t
cpu_set_t *

attr,
taille,
* cpuset);
attr,
taille,
cpuset);

Dans lexemple suivant, nous allons lancer autant de threads en parallle quil y a de processeurs disponibles. Nous commenons par le CPU0, puis incrmentons le numro jusqu ce que
lappel pthread_create() choue. Notons que la variable de type pthread_t est crase chaque
appel avec le nouvel identifiant affect au thread cr.
exemple_pthread_attr_setaffiniy.c:
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
void * fonction(void * arg)
{
long num = (long) arg;
while (1) {
printf("[Thread %ld] Je suis sur le CPU %d\n",
num, sched_getcpu());
sleep(5);
}
}
int main(void)
{
cpu_set_t
cpuset;
pthread_t
thr;
pthread_attr_t attr;
long num;
num = 0;
while (1) {
// Initialiser avec les attributs par dfaut
pthread_attr_init(& attr);
// Prparer le cpuset
CPU_ZERO(&(cpuset));

Blaess.indb 15

22/10/2015 14:15

16

Solutions temps rel sous Linux

CPU_SET(num, &(cpuset));
// Fixer l'affinit

pthread_attr_setaffinity_np(& attr,
sizeof(cpu_set_t),
& cpuset);
// Lancer le thread
if (pthread_create(& thr, & attr, fonction,
(void *) num) != 0)
break;
num++;
}
// Terminer le thread main en continuant les autres
pthread_exit(NULL);
}

Excutons ce programme sur une machine possdant quatre curs:


$ ./exemple-pthread-attr-setaffinity
[Thread 0] Je suis sur le CPU 0
[Thread 1] Je suis sur le CPU 1
[Thread 2] Je suis sur le CPU 2
[Thread 3] Je suis sur le CPU 3
[Thread 0] Je suis sur le CPU 0
[Thread 1] Je suis sur le CPU 1
[Thread 2] Je suis sur le CPU 2
[Thread 3] Je suis sur le CPU 3
[Thread 1] Je suis sur le CPU 1
[Thread 3] Je suis sur le CPU 3
[Thread 2] Je suis sur le CPU 2
[Thread 0] Je suis sur le CPU 0

Contrle-C
$

On peut remarquer que lordre daffichage des messages nest pas fig. Les threads faisant des
accs simultans la console, le noyau est oblig de se livrer un arbitrage qui peut voluer en
fonction de lactivit du systme. Nous allons examiner les diffrents tats dans lesquels peuvent
se trouver les tches et les transitions possibles entre ces tats.
Il est important de noter que laffinit ainsi fixe ne prsente pas de caractre obligatoire pour la
tche. tout moment, il lui est possible de modifier son affinit et de se dplacer ainsi vers un
autre processeur. Ce principe est tout fait suffisant pour les applications temps rel, o toutes
les tches dun systme sont habituellement configures pour un fonctionnement optimal. Si
on dsire verrouiller imprativement une tche sur un CPU ou un ensemble de CPU sans
quelle puisse en sortir ensuite, on utilisera plutt le mcanisme des cpuset. Un exemple clair est
prsent dans la page de manuel cpuset(7) accessible ainsi:
$ man 7 cpuset

Blaess.indb 16

22/10/2015 14:15

You might also like