{"id":1912,"date":"2012-04-05T09:56:04","date_gmt":"2012-04-05T08:56:04","guid":{"rendered":"http:\/\/www.blaess.fr\/christophe\/?page_id=1912"},"modified":"2012-04-05T09:56:04","modified_gmt":"2012-04-05T08:56:04","slug":"solutions-temps-reel-sous-linux-exercices-corriges","status":"publish","type":"page","link":"https:\/\/www.blaess.fr\/christophe\/livres\/solutions-temps-reel-sous-linux\/solutions-temps-reel-sous-linux-exercices-corriges\/","title":{"rendered":"S.T.R.S.L. &#8211; Exercices corrig\u00e9s"},"content":{"rendered":"<p style=\"text-align: justify;\">Voici les r\u00e9ponses aux exercices de mon livre \u00ab\u00a0Solutions temps r\u00e9el sous Linux\u00a0\u00bb. Certaines questions n&rsquo;admettent pas une r\u00e9ponse unique et vous pouvez avoir une approche tout \u00e0 fait diff\u00e9rente. N&rsquo;h\u00e9sitez pas \u00e0 me faire part de vos r\u00e9sultats, vos id\u00e9es, vos remarques concernant ces exercices&nbsp;; ceci me permettra d&rsquo;enrichir cette page de solutions.<\/p>\n<p style=\"text-align: justify;\">L&rsquo;archive compl\u00e8te des solutions des exercices se trouve ici&nbsp;: <a title=\"http:\/\/www.blaess.fr\/christophe\/files\/livres\/strsl\/corrections-strsl.tar.bz2\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/livres\/strsl\/corrections-strsl.tar.bz2\" target=\"_blank\"><strong>corrections-strsl.tar.bz2<\/strong><\/a><\/p>\n<ul>\n<li><a href=\"#chapitre_1\">Chapitre 1<\/a><\/li>\n<li><a href=\"#chapitre_2\">Chapitre 2<\/a><\/li>\n<li><a href=\"#chapitre_3\">Chapitre 3<\/a><\/li>\n<li><a href=\"#chapitre_4\">Chapitre 4<\/a><\/li>\n<li><a href=\"#chapitre_5\">Chapitre 5<\/a><\/li>\n<li><a href=\"#chapitre_6\">Chapitre 6<\/a><\/li>\n<li><a href=\"#chapitre_7\">Chapitre 7<\/a><\/li>\n<li><a href=\"#chapitre_8\">Chapitre 8<\/a><\/li>\n<li><a href=\"#chapitre_9\">Chapitre 9<\/a><\/li>\n<li><a href=\"#chapitre_10\">Chapitre 10<\/a><\/li>\n<li><a href=\"#chapitre_11\">Chapitre 11<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h1 id=\"chapitre_1\">Chapitre 1<\/h1>\n<h2>Exercice 1-1<\/h2>\n<p style=\"text-align: justify;\">Le contenu du fichier <code>\/proc\/cpuinfo<\/code> et la mani\u00e8re de l&rsquo;analyser sont d\u00e9crits page 8.<\/p>\n<h2>Exercice 1-2<\/h2>\n<p style=\"text-align: justify;\">Le fichier \u00ab\u00a0<code>solution-01-02.c<\/code>\u00a0\u00bb contient une impl\u00e9mentation possible.<\/p>\n<pre>$ <strong>gcc -o solution-01-02 solution-01-02.c -pthread -lrt<\/strong>\n$ <strong>.\/solution-01-02 <\/strong>\n  <strong>(<em>Contr\u00f4le-C<\/em>)<\/strong>\n$<\/pre>\n<h2>Exercice 1-3<\/h2>\n<p style=\"text-align: justify;\">Le fichier \u00ab\u00a0<code>solution-01-03.c<\/code>\u00a0\u00bb permet de r\u00e9aliser l&rsquo;op\u00e9ration demand\u00e9e. On suit la progression sur un autre terminal, et l&rsquo;on voit bien les passages en \u00e9tats <code>R<\/code> (<em>Running<\/em>), <code>S<\/code> (<em>Sleeping<\/em>), <code>T<\/code> (<em>Traced<\/em>).<\/p>\n<pre>$ <strong>gcc -o solution-01-03 solution-01-03.c<\/strong>\n$ <strong>.\/solution-01-03<\/strong>\n[25579] Boucle active...\n                                  $ <strong>ps aux | grep 25579 | grep -v grep<\/strong>\n                                  cpb      25579 99.8  0.0   1820   248 pts\/4    R+   10:33   0:05 .\/solution-01-03\n[25579] Sommeil...\n                                  $ <strong>ps aux | grep 25579 | grep -v grep<\/strong>\n                                  cpb      25579 97.5  0.0   1820   248 pts\/4    S+   10:33   0:14 .\/solution-01-03\n[25579] Boucle active...\n                                  $ <strong>kill -STOP 25579<\/strong>\n[1]+  Stopp\u00e9                 .\/solution-01-03\n$\n                                  $ <strong>ps aux | grep 25579 | grep -v grep<\/strong>\n                                    cpb      25579 65.1  0.0   1820   248 pts\/4    T    10:33   0:18 .\/solution-01-03\n                                  $ kill -CONT 25579\n                                  $ <strong>ps aux | grep 25579 | grep -v grep<\/strong>\n                                  cpb      25579 57.1  0.0   1820   248 pts\/4    R    10:33   0:21 .\/solution-01-03\n [25579] Sommeil...\n[25579] Boucle active...\n                                  $ <strong>kill -TERM 25579<\/strong>\n                                  $\n$<\/pre>\n<h2>Exercice 1-4<\/h2>\n<p style=\"text-align: justify;\">Une solution est impl\u00e9ment\u00e9e dans le fichier \u00ab\u00a0<code>solution-01-04.c<\/code>\u00ab\u00a0. Lorsqu&rsquo;on l&rsquo;ex\u00e9cute on voit que le processus fils devient <em>Zombie<\/em> au bout de dix secondes. Ceci signifie qu&rsquo;il est termin\u00e9 mais que son p\u00e8re n&rsquo;a pas lu son statut de terminaison.<\/p>\n<p style=\"text-align: justify;\">Les tentatives d&rsquo;envoi de signal sur le fils n&rsquo;ont aucun effet, il est d\u00e9j\u00e0 mort&nbsp;!<\/p>\n<pre>$ <strong>gcc -o solution-01-04 solution-01-04.c <\/strong>\n$ <strong>.\/solution-01-04 <\/strong>\n[27004] Je suis le processus pere...\n[27005] Je suis le processus fils...\n                                  $ <strong>ps aux | grep 27005 | grep -v grep<\/strong>\n                                  cpb      27005  0.0  0.0   1820    56 pts\/4    S+   10:47   0:00 .\/solution-01-04\n[27005] Je vais me terminer...\n                                  $ <strong>ps aux | grep 27005 | grep -v grep<\/strong>\n                                  cpb      27005  0.0  0.0      0     0 pts\/4    Z+   10:47   0:00 [solution-01-04]\n                                  $ <strong>kill -TERM 27005<\/strong>\n                                  $ <strong>ps aux | grep 27005 | grep -v grep<\/strong>\n                                  cpb      27005  0.0  0.0      0     0 pts\/4    Z+   10:47   0:00 [solution-01-04]\n                                  $ <strong>kill -INT 27005<\/strong>\n                                  $ <strong>ps aux | grep 27005 | grep -v grep<\/strong>\n                                  cpb      27005  0.0  0.0      0     0 pts\/4    Z+   10:47   0:00 [solution-01-04]\n                                  $ <strong>kill -9 27005<\/strong>\n                                  $ <strong>ps aux | grep 27005 | grep -v grep<\/strong>\n                                  cpb      27005  0.0  0.0      0     0 pts\/4    Z+   10:47   0:00 [solution-01-04]\n                                  $<\/pre>\n<p style=\"text-align: justify;\">Pour s&rsquo;en d\u00e9barasser, il faut terminer le processus p\u00e8re. Lorsqu&rsquo;un processus meurt, ses fils (zombies ou non) sont adopt\u00e9s par le processus num\u00e9ro 1 (<em>init<\/em>) qui vient lire le statut de terminaison et les zombies disparaissent alors.<\/p>\n<pre>                                  $ <strong>kill 27004<\/strong>\nComplete\n$\n                                  $ <strong>ps aux | grep 27005 | grep -v grep<\/strong>\n                                  $<\/pre>\n<h1 id=\"chapitre_2\">Chapitre 2<\/h1>\n<h2>Exercice 2-1<\/h2>\n<p style=\"text-align: justify;\">En ex\u00e9cutant \u00ab\u00a0<code>watch -n 0.1 cat \/proc\/interrupts<\/code>\u00a0\u00bb (ou <strong>0,1<\/strong> \u00e9ventuellement) vous devriez voir une interruption se d\u00e9clencher p\u00e9riodiquement. Peut-\u00eatre une interruption locale, interne au processeur. Sur la plupart des distributions actuelles, la fr\u00e9quence du timer est \u00e0 250Hz ou 300Hz. Aussi, en observant le chiffre des milliers d&rsquo;interruptions, vous devriez le voir \u00e9voluer toutes les 3 \u00e0 4 secondes.<\/p>\n<p style=\"text-align: justify;\">Ceci d\u00e9pend largement du syst\u00e8me et du noyau install\u00e9.<\/p>\n<h2>Exercice 2-2<\/h2>\n<p style=\"text-align: justify;\">En pressant une touche du clavier ou en d\u00e9pla\u00e7ant la souris vous verrez une interruption se produire. Parfois il s&rsquo;agit d&rsquo;une interruption provoqu\u00e9e par un contr\u00f4leur USB auquel le clavier ou la souris sont branch\u00e9s.<\/p>\n<h2>Exercice 2-3<\/h2>\n<p style=\"text-align: justify;\">Supposons que votre souris soit sur l&rsquo;interruption 18, et qu&rsquo;elle soit trait\u00e9e majoritairement sur le CPU 0, alors que vous disposez de quatre c\u0153urs. Vous pouvez forcer le traitement sur le c\u0153ur 2 en utilisant&nbsp;:<\/p>\n<pre># echo 4 &gt; \/proc\/irq\/18\/smp_affinity<\/pre>\n<p style=\"text-align: justify;\">La valeur a \u00e9crire est 2 puissance le num\u00e9ro du c\u0153ur voulu (num\u00e9rot\u00e9 \u00e0 partir de z\u00e9ro). Il faut avoir les droits <em>root<\/em> pour effectuer cette modification.<\/p>\n<h2>Exercice 2-4<\/h2>\n<p style=\"text-align: justify;\">Pour effectuer une division par z\u00e9ro sans que le compilateur ne s&rsquo;en rende compte et nous l&rsquo;interdise \u00e0 la compilation, il suffit d&rsquo;utiliser le nombre d&rsquo;arguments sur la ligne de commande. C&rsquo;est ce qui est impl\u00e9ment\u00e9 dans le fichier \u00ab\u00a0<code>solution-02-04.c<\/code>\u00a0\u00bb qui d\u00e9clenche bien l&rsquo;exception attendue.<\/p>\n<pre>$ <strong>.\/solution-02-04 abcdef <\/strong>\nJe vais calculer i=1\/1\nLe resultat est 1\n$ <strong>.\/solution-02-04 abcdef ghijkl<\/strong>\nJe vais calculer i=1\/2\nLe resultat est 0\n$ <strong>.\/solution-02-04 <\/strong>\nJe vais calculer i=1\/0\nException en point flottant\n$<\/pre>\n<h2>Exercice 2-5<\/h2>\n<p style=\"text-align: justify;\">Pour d\u00e9clencher l&rsquo;exception \u00ab\u00a0<em>Illegal instruction<\/em>\u00ab\u00a0, il faut ex\u00e9cuter du code invalide pour le processeur employ\u00e9. C&rsquo;est difficile avec les architectures actuelles car les pages de code sont verrouill\u00e9es en lecture seule (donc impossible de modifier des fonctions existantes) et les pages de donn\u00e9es ne sont pas ex\u00e9cutables (donc impossible d&rsquo;y d\u00e9router l&rsquo;ex\u00e9cution).<\/p>\n<p style=\"text-align: justify;\">La solution consiste \u00e0 g\u00e9n\u00e9rer un code assembleur invalide et \u00e0 l&rsquo;ins\u00e9rer manuellement dans un programme C, comme c&rsquo;est fait dans le fichier \u00ab\u00a0<code>solution-02-05.c<\/code>\u00a0\u00bb (les instructions sont invalides pour un processeur x86, il faudra peut-\u00eatre changer les valeurs si on le teste sur une autre architecture).<\/p>\n<pre>$ <strong>gcc -o solution-02-05 solution-02-05.c <\/strong>\n$ <strong>.\/solution-02-05 <\/strong>\nJ'execute la fonction avec le code invalide...\nInstruction non permise\n$<\/pre>\n<h1 id=\"chapitre_3\">Chapitre 3<\/h1>\n<h2>Exercice 3-1<\/h2>\n<p style=\"text-align: justify;\">Comme on peut s&rsquo;y attendre, le nombre de boucles par dizaine de secondes reste a peu pr\u00e8s constant, et se r\u00e9partit \u00e9quitablement entre les processus.<\/p>\n<pre>$ <strong>.\/exemple-taux-cpu <\/strong>\n[3036] nb_boucles : 79183231\n$ <strong>.\/exemple-taux-cpu &amp; .\/exemple-taux-cpu <\/strong>\n[3039] nb_boucles : 40693996\n[3040] nb_boucles : 40694974\n$ <strong>.\/exemple-taux-cpu &amp; .\/exemple-taux-cpu &amp; .\/exemple-taux-cpu <\/strong>\n[3133] nb_boucles : 26061303\n[3131] nb_boucles : 25634096\n[3132] nb_boucles : 25702652\n$<\/pre>\n<h2>Exercice 3-2<\/h2>\n<p style=\"text-align: justify;\">En utilisant la commande <code>nice<\/code> on favorise un processus par rapport \u00e0 l&rsquo;autre. Plus la valeur transmise \u00e0 <code>nice<\/code> est \u00e9lev\u00e9e, plus le processus est p\u00e9nalis\u00e9.<\/p>\n<pre>$ <strong>.\/exemple-taux-cpu &amp; nice -n +3 .\/exemple-taux-cpu <\/strong>\n[3611] nb_boucles : 25088529\n[3610] nb_boucles : 49568574\n$ <strong>.\/exemple-taux-cpu &amp; nice -n +5 .\/exemple-taux-cpu <\/strong>\n[3701] nb_boucles : 56678953\n[3702] nb_boucles : 18291412\n$ <strong>.\/exemple-taux-cpu &amp; nice -n +10 .\/exemple-taux-cpu <\/strong>\n[3705] nb_boucles : 74797470\n[3706] nb_boucles : 7845659\n$ <strong>.\/exemple-taux-cpu &amp; nice -n +20 .\/exemple-taux-cpu <\/strong>\n[3709] nb_boucles : 79928673\n[3710] nb_boucles : 1187910\n$<\/pre>\n<h2>Exercice 3-3<\/h2>\n<p style=\"text-align: justify;\">La r\u00e9daction du script shell n&rsquo;est pas \u00e9vidente car il faut lancer les vingt processus en parall\u00e8le et trier leurs r\u00e9sultats. On en trouvera un exemple dans le fichier <code>solution-03-03.sh<\/code>. Notez que les valeurs croissantes de <code>nice<\/code> correspondent aux valeurs croissantes de PID.<\/p>\n<pre>$ <strong>.\/solution-03-03.sh <\/strong>\n[3841] nb_boucles : 16599509\n[3842] nb_boucles : 13338231\n[3843] nb_boucles : 10650787\n[3844] nb_boucles : 8574728\n[3845] nb_boucles : 6903253\n[3846] nb_boucles : 5472881\n[3847] nb_boucles : 4428908\n[3848] nb_boucles : 3508128\n[3849] nb_boucles : 2801397\n[3850] nb_boucles : 1995259\n[3851] nb_boucles : 1601489\n[3852] nb_boucles : 1265770\n[3853] nb_boucles : 1044762\n[3854] nb_boucles : 910331\n[3855] nb_boucles : 749787\n[3856] nb_boucles : 584887\n[3857] nb_boucles : 486954\n[3858] nb_boucles : 389343\n[3859] nb_boucles : 285891\n[3860] nb_boucles : 251992\n$<\/pre>\n<h2>Exercice 3-4<\/h2>\n<p style=\"text-align: justify;\">Pour tester les r\u00e9sultats de l&rsquo;exercice pr\u00e9c\u00e9dent sur plusieurs versions du noyau Linux, il faut r\u00e9aliser une longue s\u00e9rie de compilations (comme indiqu\u00e9 dans l&rsquo;annexe I). J&rsquo;ai compil\u00e9 un noyau <em>Vanilla<\/em> 2.6.39.9 sur une distribution Ubuntu 11.10. La premi\u00e8re version sans l&rsquo;option <code>autogroup<\/code>, et l&rsquo;autre avec cette option. Les fichiers de configuration des noyaux se trouvent dans l&rsquo;archive des solutions.<\/p>\n<p>Les r\u00e9sultats sont les suivants, en commen\u00e7ant sur un syst\u00e8me faiblement charg\u00e9.<\/p>\n<pre><strong>Option autogroup NON activ\u00e9e<\/strong>:\n[2065] nb_boucles : 15809768\n[2066] nb_boucles : 12317797\n[2067] nb_boucles : 10108224\n[2068] nb_boucles : 7879477\n[2069] nb_boucles : 6340445\n[2070] nb_boucles : 5023591\n[2071] nb_boucles : 4191715\n[2072] nb_boucles : 3326890\n[2073] nb_boucles : 2662925\n[2074] nb_boucles : 2135578\n[2075] nb_boucles : 1701423\n[2076] nb_boucles : 1327210\n[2077] nb_boucles : 1075745\n[2078] nb_boucles : 865417\n[2079] nb_boucles : 698098\n[2080] nb_boucles : 547356\n[2081] nb_boucles : 449937\n[2082] nb_boucles : 353484\n[2083] nb_boucles : 287868\n[2084] nb_boucles : 224124<\/pre>\n<p style=\"text-align: justify;\">et<\/p>\n<pre><strong>Option autogroup activ\u00e9e<\/strong>\n[4124] nb_boucles : 16547401\n[4125] nb_boucles : 13360087\n[4126] nb_boucles : 10621702\n[4127] nb_boucles : 8524357\n[4128] nb_boucles : 6842971\n[4129] nb_boucles : 5452880\n[4130] nb_boucles : 4413384\n[4131] nb_boucles : 3516360\n[4132] nb_boucles : 2820007\n[4133] nb_boucles : 2236505\n[4134] nb_boucles : 1784830\n[4135] nb_boucles : 1423908\n[4136] nb_boucles : 1163712\n[4137] nb_boucles : 928116\n[4138] nb_boucles : 761456\n[4139] nb_boucles : 589009\n[4140] nb_boucles : 495110\n[4141] nb_boucles : 397024\n[4142] nb_boucles : 296815\n[4143] nb_boucles : 263285<\/pre>\n<p style=\"text-align: justify;\">Peu de diff\u00e9rences notables dans le comportement. Voyons \u00e0 pr\u00e9sent sur un syst\u00e8me avec une charge en processus assez \u00e9lev\u00e9e.<\/p>\n<pre><strong>Option autogroup NON activ\u00e9e<\/strong>:\n[2294] nb_boucles : 11454211\n[2295] nb_boucles : 9183630\n[2296] nb_boucles : 7472511\n[2297] nb_boucles : 6001470\n[2298] nb_boucles : 4813134\n[2299] nb_boucles : 3762535\n[2300] nb_boucles : 3110984\n[2301] nb_boucles : 2394422\n[2302] nb_boucles : 1934842\n[2303] nb_boucles : 1581542\n[2304] nb_boucles : 1235447\n[2305] nb_boucles : 988488\n[2306] nb_boucles : 819291\n[2307] nb_boucles : 644526\n[2308] nb_boucles : 514887\n[2309] nb_boucles : 419180\n[2310] nb_boucles : 326733\n[2311] nb_boucles : 255844\n[2312] nb_boucles : 222833\n[2313] nb_boucles : 188144<\/pre>\n<p style=\"text-align: justify;\">et<\/p>\n<pre><strong>Option autogroup activ\u00e9e<\/strong>\n[4362] nb_boucles : 4972521\n[4363] nb_boucles : 4015143\n[4364] nb_boucles : 3176701\n[4365] nb_boucles : 2553396\n[4366] nb_boucles : 2069002\n[4367] nb_boucles : 1648680\n[4368] nb_boucles : 1324571\n[4369] nb_boucles : 1069048\n[4370] nb_boucles : 838920\n[4371] nb_boucles : 679788\n[4372] nb_boucles : 551903\n[4373] nb_boucles : 451465\n[4374] nb_boucles : 354519\n[4375] nb_boucles : 290077\n[4376] nb_boucles : 224147\n[4377] nb_boucles : 190850\n[4378] nb_boucles : 158436\n[4379] nb_boucles : 126133\n[4380] nb_boucles : 93978\n[4381] nb_boucles : 88006<\/pre>\n<p style=\"text-align: justify;\">Dans le second cas, l&rsquo;ensemble des processus se sont partag\u00e9 le temps CPU attribu\u00e9 \u00e0 leur terminal, sans perturber excessivement les autres t\u00e2ches du syst\u00e8me. On pourra trouver plus d&rsquo;informations dans <a title=\"[ACTU] Groupement automatique des processus\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/04\/01\/groupement-automatique-des-processus\/\" target=\"_blank\">cet article<\/a>.<\/p>\n<h2>Exercice 3-5<\/h2>\n<p style=\"text-align: justify;\">Les informations sur le m\u00e9canisme des <code>cgroups<\/code> se trouvent dans le r\u00e9pertoire <code>Documentation\/cgroups<\/code> \u00e0 l&rsquo;int\u00e9rieur des sources du noyau Linux. Montons le syst\u00e8me de fichiers correspondant si ce n&rsquo;est pas fait par la distribution<\/p>\n<pre># <strong>mount | grep cgroup<\/strong>\n# <strong>mkdir -p \/dev\/cgroup<\/strong>\n# <strong>mount none \/dev\/cgroup\/ -t cgroup -o cpuset<\/strong>\n# <strong>ls \/dev\/cgroup\/<\/strong>\ncgroup.clone_children  cpuset.cpu_exclusive  cpuset.mem_hardwall     cpuset.memory_pressure_enabled  cpuset.mems                      notify_on_release\ncgroup.event_control   cpuset.cpus           cpuset.memory_migrate   cpuset.memory_spread_page       cpuset.sched_load_balance        release_agent\ncgroup.procs           cpuset.mem_exclusive  cpuset.memory_pressure  cpuset.memory_spread_slab       cpuset.sched_relax_domain_level  tasks\n#<\/pre>\n<p style=\"text-align: justify;\">Cr\u00e9ons un groupe (arbitrairement nomm\u00e9) que nous limiterons au CPU 3 de cette machine, en lui attribuan le noeud m\u00e9moire z\u00e9ro.<\/p>\n<pre># <strong>mkdir \/dev\/cgroup\/CPU-3<\/strong>\n# <strong>ls \/dev\/cgroup\/CPU-3\/<\/strong>\ncgroup.clone_children  cgroup.procs          cpuset.cpus           cpuset.mem_hardwall    cpuset.memory_pressure     cpuset.memory_spread_slab  cpuset.sched_load_balance        notify_on_release\ncgroup.event_control   cpuset.cpu_exclusive  cpuset.mem_exclusive  cpuset.memory_migrate  cpuset.memory_spread_page  cpuset.mems                cpuset.sched_relax_domain_level  tasks\n# <strong>echo 3 &gt; \/dev\/cgroup\/CPU-3\/cpuset.cpus<\/strong>\n# <strong>echo 0 &gt; \/dev\/cgroup\/CPU-3\/cpuset.mems <\/strong>\n#<\/pre>\n<p style=\"text-align: justify;\">Pla\u00e7ons notre shell (dont le PID est donn\u00e9 par la variable <code>$$<\/code>) dans ce groupe.<\/p>\n<pre># <strong>echo $$ &gt; \/dev\/cgroup\/CPU-3\/tasks<\/strong>\n#<\/pre>\n<p style=\"text-align: justify;\">V\u00e9rifions l&rsquo;affinit\u00e9 de notre shell.<\/p>\n<pre># <strong>taskset -p $$<\/strong>\npid 29562's current affinity mask: 8\n#<\/pre>\n<p style=\"text-align: justify;\">L&rsquo;affinit\u00e9 est <code>8<\/code> (<code>2^3<\/code>), le shell ne peut donc fonctionner que sur le CPU 3. Essayons de le replacer sur le CPU 0.<\/p>\n<pre># <strong>taskset -pc 0 $$<\/strong>\npid 29562's current affinity list: 3\ntaskset: failed to set pid 29562's affinity: Argument invalide\n#<\/pre>\n<p style=\"text-align: justify;\">Le d\u00e9placement n&rsquo;est pas autoris\u00e9. Les affectations par le m\u00e9canisme <code>cgroups<\/code> est plus contraignant que la simple modification de l&rsquo;affinit\u00e9. Les processus ne peuvent plus sortir des CPU qui leur ont \u00e9t\u00e9 attribu\u00e9s.<\/p>\n<p>&nbsp;<\/p>\n<h1 id=\"chapitre_4\">Chapitre 4<\/h1>\n<h2>Exercice 4-1<\/h2>\n<p style=\"text-align: justify;\">La modification de la priorit\u00e9 temps partag\u00e9 n&rsquo;a pas d&rsquo;influence sur le nombre d&rsquo;appels syst\u00e8me <code>gettimeofday()<\/code> que notre processus r\u00e9ussit \u00e0 effectuer par micro-seconde.<\/p>\n<h2>Exercice 4-2<\/h2>\n<p style=\"text-align: justify;\">Les op\u00e9rations ont \u00e9t\u00e9 d\u00e9crites pages 72 et 73, les statistiques peuvent pr\u00e9senter de grosses variations d&rsquo;une ex\u00e9cution \u00e0 l&rsquo;autre en fonction de la charge du syst\u00e8me.<\/p>\n<h2>Exercice 4-3<\/h2>\n<p style=\"text-align: justify;\">Vous devriez obtenir des histogrammes proches de ceux pr\u00e9sent\u00e9s pages 77 et 79. Il est n\u00e9cessaire d&rsquo;installer le programme Gnuplot pour disposer d&rsquo;une repr\u00e9sentation graphique. En principe on arrive a obtenir un timer de qualit\u00e9 correcte avec une p\u00e9riode de quelques millisecondes, et un syst\u00e8me peu charg\u00e9.<\/p>\n<h2>Exercice 4-4<\/h2>\n<p style=\"text-align: justify;\">Plus les perturbations externes seront fortes (tant en interruptions qu&rsquo;en charge syst\u00e8me), plus le timer fluctuera. Dans des situations extr\u00e8mes, les ecarts pourront m\u00eame d\u00e9passer la seconde.<\/p>\n<h2>Exercice 4-5<\/h2>\n<p style=\"text-align: justify;\">Les dur\u00e9es maximales des pr\u00e9emptions d\u00e9pendent tr\u00e8s fortement du mat\u00e9riel, de sa charge en interruption et de sa charge en processus. Sur un syst\u00e8me peu charg\u00e9, il ne doit pas y avoir de pr\u00e9emption sup\u00e9rieure \u00e0 une milliseconde. On peut s&rsquo;en assurer ainsi.<\/p>\n<pre>$ .\/exemple-gettimeofday-02 1000\n$<\/pre>\n<p style=\"text-align: justify;\">Pour affiner l&rsquo;exp\u00e9rience, il peut s&rsquo;av\u00e9rer n\u00e9cessaire d&rsquo;allonger la dur\u00e9e initiale de \u00ab\u00a0<code>exemple-gettimeofday-02.c<\/code>\u00a0\u00bb (ligne 51, la dur\u00e9e initiale est de cinq secondes).<\/p>\n<h1 id=\"chapitre_5\">Chapitre 5<\/h1>\n<h2>Exercice 5-1<\/h2>\n<p style=\"text-align: justify;\">Le script \u00ab\u00a0<code>cherche-taches-rt.sh<\/code>\u00a0\u00bb permet d&rsquo;afficher les param\u00e8tres des processus ordonnanc\u00e9s <em>Round Robin<\/em> ou <em>Fifo<\/em>. En voici un exemple d&rsquo;utilisation.<\/p>\n<pre>$ <strong>.\/cherche-taches-rt.sh<\/strong>\npid 11's current scheduling policy: SCHED_FIFO\npid 11's current scheduling priority: 99\npid 14's current scheduling policy: SCHED_FIFO\npid 14's current scheduling priority: 99\npid 21514's current scheduling policy: SCHED_RR\npid 21514's current scheduling priority: 1\npid 6's current scheduling policy: SCHED_FIFO\npid 6's current scheduling priority: 99\npid 7's current scheduling policy: SCHED_FIFO\npid 7's current scheduling priority: 99\n$<\/pre>\n<h2>Exercice 5-2<\/h2>\n<p style=\"text-align: justify;\">Il faut disposer des droit <em>root<\/em> (ou employer <code>sudo<\/code>) pour passer l&rsquo;ordonnancement d&rsquo;une t\u00e2che en temps r\u00e9el. Pour modifier l&rsquo;ordonnancement du shell, on peut employer la variable <code>$$<\/code> qui est toujours initialis\u00e9e avec son propre PID.<\/p>\n<pre>$ sudo chrt -pf 10 $$\n[sudo] password for cpb:<\/pre>\n<p style=\"text-align: justify;\">On peut v\u00e9rifier l&rsquo;ordonnancement configur\u00e9 avec <code>chrt<\/code> \u00e9galement.<\/p>\n<pre>$ chrt -p $$\npid 11868's current scheduling policy: SCHED_FIFO\npid 11868's current scheduling priority: 10\n$<\/pre>\n<p style=\"text-align: justify;\">Le shell ne pr\u00e9sente pas de modification de son comportement, mais tous les processus qu&rsquo;il lance d\u00e9marreront en temps r\u00e9el.<\/p>\n<h2>Exercice 5-3<\/h2>\n<p style=\"text-align: justify;\">Le script <code>passer-taches-rt.sh<\/code> passe en ordonnancement Fifo priorit\u00e9 10 tous les processus initialement en temps partag\u00e9. Le syst\u00e8me fonctionne tout \u00e0 fait normalement. Il peut y avoir n\u00e9anmoins des p\u00e9riodes de gel temporaire de l&rsquo;activit\u00e9 lorsqu&rsquo;on ex\u00e9cute des processus qui consomme beaucoup de CPU (calcul, compilation, etc.).<\/p>\n<h2>Exercice 5-4<\/h2>\n<p style=\"text-align: justify;\">Au lancement du programme le syst\u00e8me semble fig\u00e9, mais quelques t\u00e2ches temps partag\u00e9 arrivent \u00e0 s&rsquo;ex\u00e9cuter quand m\u00eame, \u00e0 cause du param\u00e8tre <code>\/proc\/sys\/kernel\/sched_rt_runtime_us<\/code> comme indiqu\u00e9 page 99. En \u00e9crivant <code>-1<\/code> dans ce pseudo-fichier, on peut geler temporairement tout le syst\u00e8me avec des boucles actives.<\/p>\n<h2>Exercice 5-5<\/h2>\n<p style=\"text-align: justify;\">Il n&rsquo;est pas simple de trouver toutes les t\u00e2ches \u00e0 passer en temps r\u00e9el pour conserver le contr\u00f4le de l&rsquo;interface graphique malgr\u00e9 la boucle active. J&rsquo;ai d\u00e9j\u00e0 remarqu\u00e9 que les fen\u00eatres des terminaux en mode texte semblent recevoir des rafales de retours-chariot si elles n&rsquo;ont pas d&rsquo;acc\u00e8s au CPU pendant un temps prolong\u00e9. Je suppose que cela est li\u00e9 \u00e0 un d\u00e9lai de <em>timeout<\/em> qui expire et correspond \u00e0 l&rsquo;\u00e9mission d&rsquo;un caract\u00e8re <em>break<\/em> vers le terminal.<\/p>\n<h1 id=\"chapitre_6\">Chapitre 6<\/h1>\n<h2>Exercice 6-1<\/h2>\n<p style=\"text-align: justify;\">L&rsquo;ex\u00e9cution de <code>exemple-timer-create-02.c<\/code> sous un ordonnancement temps r\u00e9el permet d&rsquo;obtenir un r\u00e9sultat plus fiable (mais pas plus rapide bien s\u00fbr) qu&rsquo;en temps partag\u00e9. Les fluctuations devraient se compter en dizaines de micro-secondes<\/p>\n<h2>Exercice 6-2<\/h2>\n<p style=\"text-align: justify;\">Le programme <code>exemple-perturbateur.c<\/code> cr\u00e9ant essentiellement de la charge CPU en temps partag\u00e9, il n&rsquo;a que tr\u00e8s peu d&rsquo;influence sur le timer. Si on l&rsquo;ordonnance en temps-r\u00e9el, il pourra perturber tr\u00e8s violement le timer aussit\u00f4t que leurs priorit\u00e9s seront identiques.<\/p>\n<h2>Exercice 6-3<\/h2>\n<p style=\"text-align: justify;\">Sur la plupart des syst\u00e8mes, la fluctuation d&rsquo;un timer (l&rsquo;\u00e9cart type des p\u00e9riodes mesur\u00e9es) reste inf\u00e9rieure \u00e0 5% de la p\u00e9riode si celle-ci est de l&rsquo;ordre d&rsquo;une cinquantaine de microsecondes au minimum.<\/p>\n<h2>Exercice 6-4<\/h2>\n<p style=\"text-align: justify;\">La mesure du temps de commutation entre threads synchronis\u00e9s par un mutex peut se faire en employant le programme \u00ab\u00a0<code>exemple-commutations-threads.c<\/code>\u00a0\u00bb de la mani\u00e8re d\u00e9crite pages 117 \u00e0 120. Pour r\u00e9aliser la m\u00eame mesure sur des processus sycnhronis\u00e9s par un s\u00e9maphore, employez le programme \u00ab\u00a0<code>exemple-commutation-processus.c<\/code>\u00a0\u00bb tel qu&rsquo;indiqu\u00e9 page 121.<\/p>\n<p style=\"text-align: justify;\">Les temps de commutation entre processus peuvent \u00eatre l\u00e9g\u00e8rement plus longs, ceci \u00e9tant d\u00fb \u00e0 la m\u00e9moire virtuelle, et \u00e0 la n\u00e9cessit\u00e9 de modifier la configuration de la MMU.<\/p>\n<h2>Exercice 6-5<\/h2>\n<p style=\"text-align: justify;\">Vous trouverez des exemples de mesure de l&rsquo;efficacit\u00e9 des outils de synchronisation et de communication entre processus dans les articles suivants.<\/p>\n<ul>\n<li><a title=\"Efficacit\u00e9 des IPC&nbsp;: les files de messages Posix\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/09\/17\/efficacite-des-ipc-les-files-de-messages-posix\/\">Efficacit\u00e9 des IPC &#8211; Les files de messages Posix<\/a><\/li>\n<li><a title=\"Efficacit\u00e9 des IPC&nbsp;: les signaux temps-r\u00e9el\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/10\/02\/efficacite-des-ipc-les-signaux-temps-reel\/\">Efficacit\u00e9 des IPC &#8211; Les signaux temps-r\u00e9el<\/a><\/li>\n<li><a title=\"Efficacite des IPC&nbsp;: s\u00e9maphore et m\u00e9moire partag\u00e9e\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/10\/09\/efficacite-des-ipc-semaphore-et-memoire-partagee\/\">Efficacit\u00e9 des IPC &#8211; S\u00e9maphores et m\u00e9moire partag\u00e9e<\/a><\/li>\n<\/ul>\n<h1 id=\"chapitre_7\">Chapitre 7<\/h1>\n<h2>Exercice 7-1<\/h2>\n<p style=\"text-align: justify;\">Pour synchroniser le d\u00e9marrage de plusieurs processus distincts, il est possible de verrouiller un s\u00e9maphore Posix avant leur lancement (ou de l&rsquo;initialiser avec un compteur \u00e0 z\u00e9ro). Chaque processus demande le s\u00e9maphore (et reste donc bloqu\u00e9 initialment) puis le rel\u00e2che imm\u00e9diatement.<\/p>\n<p style=\"text-align: justify;\">Le processus principal, apr\u00e8s avoir cr\u00e9\u00e9 tous les processus fils va les laisser d\u00e9marrer en rel\u00e2chant le s\u00e9mpahore. Vous en trouverez une impl\u00e9mentation dans le fichier <code>solution-07-01.c<\/code>.<\/p>\n<h2>Exercice 7-2<\/h2>\n<p style=\"text-align: justify;\">L&rsquo;impl\u00e9mentation propos\u00e9 dans \u00ab\u00a0<code>solution-07-02.c<\/code>\u00a0\u00bb nous d\u00e9montre qu&rsquo;une situation d&rsquo;inversion de priorit\u00e9 peut se produire sur un s\u00e9maphore (P2 s&rsquo;ex\u00e9cute avant P3).<\/p>\n<pre># <strong>.\/solution-07-02 <\/strong>\nP1 demarre\nP1 demande le sempahore\nP1 tient le semaphore\nP1 cree P3\n        P3 demarre\n        P3 demande le semaphore\nP1 cree P2\n    P2 demarre\n    P2 se termine\nP1 lache le semaphore\n        P3 tient le sempahore\n        P3 lache le semaphore\n        P3 se termine\nP1 se termine\n#<\/pre>\n<p style=\"text-align: justify;\">Il n&rsquo;existe pas d&rsquo;h\u00e9ritage de priorit\u00e9 sur les s\u00e9maphores, car \u00e0 la diff\u00e9rence des mutex, ceux-ci n&rsquo;ont pas de propri\u00e9taire. Un s\u00e9maphore est essentiellement un compteur, qui peut prendre une valeur positive ou nulle. Lorsque le s\u00e9maphore est \u00e0 z\u00e9ro, n&rsquo;importe quel processus peut l&rsquo;incr\u00e9menter. Il n&rsquo;y a pas de notion de processus qui \u00ab\u00a0tient\u00a0\u00bb le s\u00e9maphore, comme un thread tient un mutex.<\/p>\n<h2>Exercice 7-3<\/h2>\n<p style=\"text-align: justify;\">Sur un syst\u00e8me o\u00f9 les mutex n&rsquo;offrent pas d&rsquo;h\u00e9ritage de priorit\u00e9, une solution classique pour \u00e9viter les inversions de priorit\u00e9, est de rendre un thread non-pr\u00e9emptible d\u00e8s qu&rsquo;il tient un objet de synchronisation. Sur certains syst\u00e8mes d&rsquo;exploitation, on r\u00e9alise ceci en bloquant les interruptions. Pour travailler de mani\u00e8re portable, je proposerai plut\u00f4t de monter la priorit\u00e9 du thread tenant un mutex \u00e0 la valeur la plus \u00e9lev\u00e9e possible.<\/p>\n<p style=\"text-align: justify;\">Dans le fichier \u00ab\u00a0<code>solution-07-03.c<\/code>\u00a0\u00bb j&rsquo;ai encapsul\u00e9 les appels <code>pthread_mutex_lock()<\/code> et <code>pthread_mutex_unlock()<\/code> dans des fonctions qui modifient la priorit\u00e9 du thread appelant. Notez que le r\u00e9sultat d&rsquo;ex\u00e9cution \u00e9vite bien l&rsquo;inversion de priorit\u00e9, mais n&rsquo;est pas tout \u00e0 fait identique \u00e0 celui obtenu page 147 avec le <em>Priority Inheritance Protocol<\/em>.<\/p>\n<pre># <strong>.\/solution-07-03<\/strong>\nT1 demarre\nT1 demande le mutex\nT1 tient le mutex\nT1 cree T3\nT1 cree T2\nT1 lache le mutex\n        T3 demarre\n        T3 demande le mutex\n        T3 tient le mutex\n        T3 lache le mutex\n        T3 se termine\n    T2 demarre\n    T2 se termine\nT1 se termine\n#<\/pre>\n<h2>Exercice 7-4<\/h2>\n<p style=\"text-align: justify;\">Le fichier \u00ab\u00a0<code>solution-07-04.c<\/code>\u00a0\u00bb permet de s&rsquo;assurer qu&rsquo;un s\u00e9maphore est bien obtenu par le processus le plus prioritaire qui le demande. Dans le cas d&rsquo;un ordonnancement en <em>Round Robin<\/em>, les processus obtiennent le s\u00e9maphore dans l&rsquo;ordre d&rsquo;arriv\u00e9e (l&rsquo;ordre de demande).<\/p>\n<h2>Exercice 7-5<\/h2>\n<p style=\"text-align: justify;\">Pour qu&rsquo;il y ait un partage \u00e9quitable de l&rsquo;acc\u00e8s au s\u00e9maphore, et que les processus l&rsquo;obtiennent les uns apr\u00e8s les autres, il est n\u00e9cessaire d&rsquo;introduire un appel \u00e0 <code>sched_yield()<\/code>, comme nous en avons parl\u00e9 page 159.<\/p>\n<pre># <strong>chrt -r 10 .\/solution-07-05 &amp; chrt -r 10 .\/solution-07-05 &amp; chrt -r 10 .\/solution-07-05 &amp;<\/strong>\n[1] 15403\n[2] 15404\n[3] 15405\n#\n[15405] demande le semaphore\n   [15405] tient le semaphore\n[15404] demande le semaphore\n[15403] demande le semaphore\n   [15405] lache le semaphore\n   [15404] tient le semaphore\n[15405] demande le semaphore\n   [15404] lache le semaphore\n   [15403] tient le semaphore\n[15404] demande le semaphore\n   [15403] lache le semaphore\n   [15405] tient le semaphore\n[15403] demande le semaphore\n   [15405] lache le semaphore\n   [15404] tient le semaphore\n[15405] demande le semaphore\n   [15404] lache le semaphore\n   [15403] tient le semaphore\n[15404] demande le semaphore\n   [15403] lache le semaphore\n   [15405] tient le semaphore\n[15403] demande le semaphore\n   [15405] lache le semaphore\n   [15404] tient le semaphore\n[15405] demande le semaphore\n   [15404] lache le semaphore\n   [15403] tient le semaphore\n[15404] demande le semaphore\n   [15403] lache le semaphore\n   [15405] tient le semaphore\n[15403] demande le semaphore\n# <strong>killall solution-07-05<\/strong>\n   [15405] lache le semaphore\n   [15404] tient le semaphore\n   [15404] lache le semaphore\n   [15403] tient le semaphore\n   [15403] lache le semaphore\n[1]   Compl\u00e9t\u00e9              chrt -r 10 .\/solution-07-05\n[2]-  Compl\u00e9t\u00e9              chrt -r 10 .\/solution-07-05\n[3]+  Compl\u00e9t\u00e9              chrt -r 10 .\/solution-07-05\n#<\/pre>\n<h1 id=\"chapitre_8\">Chapitre 8<\/h1>\n<h2>Exercice 8-1<\/h2>\n<p style=\"text-align: justify;\">Pour compiler un noyau modifi\u00e9 avec le patch Linux-rt, je vous conseille de vous reporter aux pages 169 et 170, ainsi qu&rsquo;aux articles suivants.<\/p>\n<ul>\n<li><a title=\"[ACTU] Nouveau Patch Linux Preempt-RT 2.6.33.9-rt31\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/04\/22\/nouveau-patch-linux-preempt-rt-2-6-33-9-rt31\/\">Nouveau patch Linux Preempt-Rt<\/a><\/li>\n<li><a title=\"Construire son syst\u00e8me personnel sur une carte Pandaboard (1)\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/05\/06\/construire-son-systeme-personnel-sur-une-carte-pandaboard\/\">Construire son syst\u00e8me personnel sur carte Pandaboard &#8211; 1<\/a><\/li>\n<li><a title=\"Compilation de Linux avec une toolchain embarqu\u00e9e native\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/07\/10\/957\/\">Compilation de Linux avec une toolchain embarqu\u00e9e native<\/a><\/li>\n<\/ul>\n<h2>Exercice 8-2<\/h2>\n<p style=\"text-align: justify;\">Les r\u00e9sultats obtenus avec \u00ab\u00a0<code>exemple-timer-create-02.c<\/code>\u00a0\u00bb sur un noyau modifi\u00e9 avec le patch Linux-rt devraient \u00eatre plus fiables qu&rsquo;avec le noyau <em>vanilla<\/em> si le processus est ex\u00e9cut\u00e9 avec une priorit\u00e9 assez \u00e9lev\u00e9e. Les diff\u00e9rences appara\u00eetront lorsque la charge en interruption augmente (avec un <em>ping flood<\/em> par exemple).<\/p>\n<h2>Exercice 8-3<\/h2>\n<p style=\"text-align: justify;\">Sur un noyau <em>vanilla<\/em>, une boucle active de priorit\u00e9 \u00e9lev\u00e9e est pr\u00e9empt\u00e9e par le noyau d\u00e8s qu&rsquo;une op\u00e9ration est \u00e0 r\u00e9aliser en r\u00e9ponse \u00e0 une interruption. Et les t\u00e2ches r\u00e9seau d&rsquo;un noyau standard sont consid\u00e9r\u00e9es comme suffisamment prioritaires pour \u00eatre trait\u00e9es directement \u00e0 la r\u00e9ception de l&rsquo;interruption. Ainsi, m\u00eame si une t\u00e2che de priorit\u00e9 <em>Fifo<\/em> 99 est active, on l&rsquo;interrompra pour r\u00e9pondre \u00e0 un <em>ping<\/em>. Avec un noyau modifi\u00e9 Linux-rt, les traitements en r\u00e9ponse aux interruptions sont effectu\u00e9s dans des <em>threads<\/em> du kernel, ordonnanc\u00e9s avec une priorit\u00e9 temps-r\u00e9el 50. Si une t\u00e2che utilisateur est active avec une priorit\u00e9 sup\u00e9rieure, les <em>threads<\/em> du noyau (et donc la r\u00e9ponse au <em>ping<\/em>), seront retard\u00e9s jusqu&rsquo;\u00e0 la fin de la t\u00e2che de haute priorit\u00e9.<\/p>\n<h2>Exercice 8-4<\/h2>\n<p style=\"text-align: justify;\">Si vous montez le <em>thread<\/em> kernel correspondant \u00e0 l&rsquo;interface r\u00e9seau \u00e0 une priorit\u00e9 sup\u00e9rieure \u00e0 celle de la boucle, le syst\u00e8me r\u00e9pond \u00e0 nouveau au <em>ping<\/em>.<\/p>\n<h2>Exercice 8-5<\/h2>\n<p style=\"text-align: justify;\">On trouvera les \u00e9l\u00e9ments de r\u00e9ponse dans <a title=\"Modifier facilement la fr\u00e9quence processeur\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/04\/30\/modifier-facilement-la-frequence-processeur\/\" target=\"_blank\">cet article<\/a>.<\/p>\n<h1 id=\"chapitre_9\">Chapitre 9<\/h1>\n<h2>Exercice 9-1<\/h2>\n<p style=\"text-align: justify;\">Vous trouverez la derni\u00e8re version de Xenomai ici&nbsp;: <a title=\"http:\/\/www.xenomai.org\/\" href=\"http:\/\/www.xenomai.org\/\" target=\"_blank\">http:\/\/www.xenomai.org\/<\/a><\/p>\n<p style=\"text-align: justify;\">T\u00e9l\u00e9chargez l&rsquo;archive, d\u00e9compressez-la, et v\u00e9rifiez le patch le plus r\u00e9cent pour votre architecture. T\u00e9l\u00e9chargez le noyau Linux (sur <a title=\"http:\/\/www.kernel.org\" href=\"http:\/\/www.kernel.org\" target=\"_blank\">http:\/\/www.kernel.org<\/a>) correspondant. Vous trouverez les d\u00e9tails pages 193 et 194.<\/p>\n<h2>Exercice 9-2<\/h2>\n<p style=\"text-align: justify;\">Pour la compilation du noyau avec Xenomai, je vous propose un <a title=\"Xenomai 2.6.0 sur Ubuntu 11.10\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/12\/28\/xenomai-2-6-0-sur-ubuntu-11-10\/\" target=\"_blank\">premier article<\/a> (installation sur une distribution Ubuntu) et <a title=\"Xenomai sur Pandaboard\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/11\/27\/xenomai-sur-pandaboard\/\" target=\"_blank\">un second<\/a> sur carte \u00e0 processeur Arm.<\/p>\n<h2>Exercice 9-3<\/h2>\n<p style=\"text-align: justify;\">Apr\u00e8s compilation des biblioth\u00e8ques (voir pages 197 et 198), le programme <code>latency<\/code> vous permettre d&rsquo;obtenir des r\u00e9sultats similaires \u00e0 ceux pr\u00e9sent\u00e9s\u00a0 page 201.<\/p>\n<h2>Exercice 9-4<\/h2>\n<p style=\"text-align: justify;\">Les r\u00e9sultats de cette exp\u00e9rience sont tr\u00e8s variables d&rsquo;une architecture \u00e0 l&rsquo;autre. Sur les PC on remarque souvent des fluctuations plus importantes sur des machines de bureau que sur des postes industriels. A titre d&rsquo;exemple, sur un PC industriel avec une charge tr\u00e8s \u00e9lev\u00e9 en interruptions et en processus, j&rsquo;ai observ\u00e9 en une journ\u00e9e une fluctuation maximale de 36 microsecondes sur un timer programm\u00e9 \u00e0 10kHz.<\/p>\n<h1 id=\"chapitre_10\">Chapitre 10<\/h1>\n<h2>Exercice 10-1<\/h2>\n<p style=\"text-align: justify;\">Le programme \u00ab\u00a0<code>solution-10-01.c<\/code>\u00a0\u00bb propose une impl\u00e9mentation de boucle active de 10 secondes sur tous les CPU. Pendant l&rsquo;ex\u00e9cution, tout le syst\u00e8me est gel\u00e9. Depuis un autre poste, le <em>ping<\/em> se comporte ainsi:<\/p>\n<pre>$ <strong>ping 192.168.3.1<\/strong>\n64 bytes from 192.168.3.1: icmp_req=41 ttl=64 time=0.660 ms\n64 bytes from 192.168.3.1: icmp_req=42 ttl=64 time=0.838 ms\n                   (ex\u00e9cution du programme)\n64 bytes from 192.168.3.1: icmp_req=43 ttl=64 time=9936 ms\n64 bytes from 192.168.3.1: icmp_req=44 ttl=64 time=8937 ms\n64 bytes from 192.168.3.1: icmp_req=45 ttl=64 time=7937 ms\n64 bytes from 192.168.3.1: icmp_req=46 ttl=64 time=6937 ms\n64 bytes from 192.168.3.1: icmp_req=47 ttl=64 time=5937 ms\n64 bytes from 192.168.3.1: icmp_req=48 ttl=64 time=4937 ms\n64 bytes from 192.168.3.1: icmp_req=49 ttl=64 time=3938 ms\n64 bytes from 192.168.3.1: icmp_req=50 ttl=64 time=2938 ms\n64 bytes from 192.168.3.1: icmp_req=51 ttl=64 time=1938 ms\n64 bytes from 192.168.3.1: icmp_req=52 ttl=64 time=938 ms\n64 bytes from 192.168.3.1: icmp_req=53 ttl=64 time=0.840 ms\n64 bytes from 192.168.3.1: icmp_req=54 ttl=64 time=0.843 ms<\/pre>\n<h2>Exercice 10-2<\/h2>\n<p style=\"text-align: justify;\">Le programme \u00ab\u00a0<code>solution-10-02.c<\/code>\u00a0\u00bb permet de mesurer la dur\u00e9e d&rsquo;une boucle programm\u00e9e avec <code>rt_timer_spin()<\/code>. La dur\u00e9e th\u00e9orique est 1 seconde, les valeurs affich\u00e9es sont des nanosecondes.<\/p>\n<pre># <strong>.\/solution-10-02 <\/strong>\nduree : 1000018442\nduree : 1000029363\nduree : 1000011173\nduree : 1000016787\nduree : 1000011203<\/pre>\n<p style=\"text-align: justify;\">Nous voyons des fluctuations de l&rsquo;ordre de quelques dizaines de microsecondes<\/p>\n<h2>Exercice 10-3<\/h2>\n<p style=\"text-align: justify;\">Apparemment, les fluctuations avec <code>rt_task_sleep()<\/code> sont un peu plus importantes qu&rsquo;avec <code>rt_timer_spin()<\/code> comme en t\u00e9moigne le programme \u00ab\u00a0<code>solution-10-03.c<\/code>\u00a0\u00bb dont les r\u00e9sultats sont les suivants. Obtenez-vous la m\u00eame conclusion&nbsp;?<\/p>\n<pre># <strong>.\/solution-10-03 <\/strong>\nduree : 1000027833\nduree : 1000041888\nduree : 1000023600\nduree : 1000031104\nduree : 1000040409\nduree : 1000029946\nduree : 1000029999<\/pre>\n<h2>Exercice 10-4<\/h2>\n<p style=\"text-align: justify;\">Le programme \u00ab\u00a0<code>solution-10-04.c<\/code>\u00a0\u00bb affiche les variations des periodes mesur\u00e9es par les timers lanc\u00e9s sur chaque CPU. Les p\u00eariodes th\u00e9oriques (en microsecondes) sont 100, 200, 300, etc. Les fluctuations mesur\u00e9es sont affich\u00e9es \u00e9galement en microsecondes. Suivant les machines, les fluctuations peuvent aller de quelques microsecondes \u00e0 quelques dizaines de microsecondes.<\/p>\n<h1 id=\"chapitre_11\">Chapitre 11<\/h1>\n<h2>Exercice 11-1<\/h2>\n<p style=\"text-align: justify;\">Il existe de nombreuses solutions possibles. Une impl\u00e9mentation est fournie dans le fichier \u00ab\u00a0<code>solution-11-01.c<\/code>\u00a0\u00bb mais elle pourrait \u00eatre am\u00e9lior\u00e9e.<\/p>\n<pre># <strong>insmod .\/solution-11-01.ko <\/strong>\n# <strong>echo AZERTY &gt; \/dev\/solution_11_01 <\/strong>\n# <strong>echo UIOP &gt; \/dev\/solution_11_01 <\/strong>\n# <strong>echo QSDF &gt; \/dev\/solution_11_01 <\/strong>\n# <strong>cat \/dev\/solution_11_01 <\/strong>\nAZERTY\n# <strong>cat \/dev\/solution_11_01 <\/strong>\nUIOP\n# <strong>cat \/dev\/solution_11_01 <\/strong>\nQSDF\n# <strong>cat \/dev\/solution_11_01 <\/strong>\n# <strong>rmmod solution_11_01 <\/strong>\n#<\/pre>\n<h2>Exercice 11-2<\/h2>\n<p style=\"text-align: justify;\">Le modules \u00ab\u00a0<code>solution-11-02.c<\/code>\u00a0\u00bb pr\u00e9sente une solution possible. La gestion de l&rsquo;offset dans la m\u00e9thode <code>read()<\/code> est un peu rudimentaire&#8230; Sur mon poste de travail, la souris d\u00e9clenche l&rsquo;interruption 18.<\/p>\n<pre># <strong>insmod .\/solution-11-02.ko numero_irq=18<\/strong>\n# <strong>cat \/dev\/solution_11_02 <\/strong>\n0\n     <em>(quelques mouvements de souris)<\/em>\n# <strong>cat \/dev\/solution_11_02<\/strong>\n93\n     <em>(quelques mouvements de souris)<\/em>\n# <strong>cat \/dev\/solution_11_02 <\/strong>\n116\n# <strong>cat \/dev\/solution_11_02 <\/strong>\n0\n# <strong>rmmod solution_11_02 <\/strong>\n#<\/pre>\n<h2>Exercice 11-3<\/h2>\n<p>La solution de cet exercice a fait l&rsquo;objet d&rsquo;<a title=\"Mesure de pr\u00e9cision des timers de RTDM \/ Xenomai\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/05\/07\/mesure-de-precision-des-timers-de-rtdm-xenomai\/\" target=\"_blank\">un article<\/a>. N&rsquo;h\u00e9sitez pas \u00e0 m&rsquo;envoyer les r\u00e9sultats que vous obtenez.<\/p>\n<h2>Exercice 11-4<\/h2>\n<p>Vous trouverez un exemple de code r\u00e9alisant le travail demand\u00e9 dans <a title=\"GPIO, Pandaboard et temps r\u00e9el \u2013 2 \u2013 sorties depuis l\u2019espace kernel\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/05\/14\/gpio-pandaboard-et-temps-reel-2-sorties-depuis-lespace-kernel\/\" target=\"_blank\">cet article<\/a>, mais je vous conseille de commencer par la lecture de <a title=\"GPIO, Pandaboard et temps r\u00e9el \u2013 1 \u2013 Sorties depuis l\u2019espace utilisateur\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/05\/09\/gpio-pandaboard-temps-reel-1\/\" target=\"_blank\">celui-ci<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Voici les r&eacute;ponses aux exercices de mon livre &laquo;&nbsp;Solutions temps r&eacute;el sous Linux&nbsp;&raquo;. Certaines questions n&rsquo;admettent pas une r&eacute;ponse unique et vous pouvez avoir une approche tout &agrave; fait diff&eacute;rente. N&rsquo;h&eacute;sitez pas &agrave; me faire part de vos r&eacute;sultats, vos id&eacute;es, vos remarques concernant ces exercices&nbsp;; ceci me permettra d&rsquo;enrichir cette page de solutions. L&rsquo;archive [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"parent":1916,"menu_order":1,"comment_status":"open","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-1912","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/pages\/1912","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/comments?post=1912"}],"version-history":[{"count":0,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/pages\/1912\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/pages\/1916"}],"wp:attachment":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/media?parent=1912"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}