Vous êtes sur la page 1sur 100

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.

fr) - 10 dcembre 2012 16:20

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

SOMMAIRE
LABO

N153

DITORIAL
Pourquoi moi je dis GNU/Linux ? Linux ou GNU/Linux est un troll^Wsujet rcurrent dans notre petit monde. Il est vrai que cest toujours loccasion de commenter, critiquer, argumenter, ... sur diffrentes bases philosophiques, linguistiques, sociales, ... Il y a cependant des cas o le sujet est abord de manire si nave et maladroite que linitiateur ne fait que dmontrer son manque de connaissances sur le sujet, avec des affirmations comme [...] pour certains, Ubuntu et Linux sont deux choses diffrentes. (rcent billet dun geek accompli sur CNET). Cest un sujet sensible, alors je ne vous dirai pas comment appeler le systme que vous utilisez. Je vous dirai simplement pourquoi moi je lappel GNU/Linux. Pour cela, jai ramen la question sa forme la plus simple et sa base de rflexion la plus tangible. Tout ce qui est sentimental, idologique, motionnel et philosophique est donc temporairement mis de ct (a aide, vous nimaginez pas). On se retrouve ainsi avec des faits, un systme compos dun noyau, historiquement appel Linux par son crateur, et dune myriade dautres lments. Parmi ces lments, un trs grand nombre proviennent du projet GNU, donc la Libc, Bash, GCC, les binutils, GDB, GRUB pour les plus gros , mais aussi gzip, find, grep, tar, les autotools, Emacs, Parted, Mailman, GNUPG, ... Sans oublier les langages et implmentations Awk, Lisp, Smalltalk, Eiffel, R, Octave, ... Et je ne parle mme pas de toutes les bibliothques ! La masse de code est NORME, tout comme le travail qui en est la source, ce qui pour moi justifie seul lutilisation des trois lettres de GNU dans le nom du systme. Il y a dautres gros morceaux dans GNU/Linux, comme Xorg, mais cest sans commune mesure avec GNU. Voil ! a sarrte l et jessaie de faire attention ne pas oublier GNU dans GNU/Linux, afin dafficher le respect que jestime devoir tmoigner ces dveloppeurs pour le travail titanesque quils ont fait pour moi. Jessaie galement, le plus souvent possible, de citer les auteurs des outils que je mentionne, ou encore de dire Vim et non Vi quand je parle de mon diteur. Bien sr, dans une conversation, quelques Linux fuseront, car le raccourci est facile et tellement courant. Des raccourcis, tout le monde en fait, comme frigo (rduction de Frigidaire) pour rfrigrateur, Kleenex pour mouchoir, Sopalin pour essuie-tout, ... Il est difficile de faire preuve de prcision de manire constante, surtout loral, mme si parfois cest trs amusant de signifier quelquun que non, son fruit prfr ne peut pas tre la fraise ou quil ne mange jamais de fruits du pommier mais au contraire les jette systmatiquement. Moi, jaime signifier ce respect et cette reconnaissance en utilisant GNU/Linux , dautres prfrent autre chose, ou encore utilisent aussi cette dsignation, mais pour dautres raisons.

04 La rception radiofrquence dfinie par logiciel (Software Defined Radio SDR)

En COUVeRTURe Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20
34

Systemd vainqueur de Upstart et des scripts System V?


Aprs plus de 30 ans de service (!), le vnrable processus init et ses scripts de service disparaissent petit petit des systmes Unix et de nos distributions Linux prfres. Si la technologie Upstart est connue des adeptes d'Ubuntu, quel sera le remplaant sur RedHat, Debian et les autres? systemd trs probablement... L'objectif de cet article est de vous prparer la migration vers cette nouvelle technologie.

SYSADMIN
43 la dcouverte de Samba 4 50 Sauvegarde et clonage chaud de vos machines avec MondoRescue

NeTADmIn
58 Testez vos applications web avec JMeter

MObILIT
64 la dcouverte d'Android : Le systme graphique

CODe(S)
75 PHP5: la magie continue 80 01:59:60 : Une seconde SVP ! 84 C++ 11 et GCC

AbOnnemenTS
41/73/74 Bons d'abonnement et de commande
Responsable publicit : Valrie Frchard, Tl. : 03 67 10 00 27 v.frechard@ed-diamond.com Service abonnement : Tl. : 03 67 10 00 20 Impression : VPM Druck Rastatt / Allemagne

GNU/Linux Magazine France est dit par Les ditions Diamond

Distribution France : (uniquement pour les dpositaires de presse) B.P. 20142 67603 Slestat Cedex Tl. : 03 67 10 00 20 Fax : 03 67 10 00 21 E-mail : lecteurs@gnulinuxmag.com Service commercial : abo@gnulinuxmag.com Sites :  www.gnulinuxmag.com www.ed-diamond.com Directeur de publication : Arnaud Metzler Rdacteur en chef : Denis Bodor Secrtaire de rdaction : Vronique Sittler Ralisation graphique : Kathrin Scali MLP Rassort : Plate-forme de Saint-Barthlemy-dAnjou. Tl. : 02 41 27 53 12 Plate-forme de Saint-Quentin-Fallavier. Tl. : 04 74 82 63 04 Service des ventes : Distri-mdias : Tl. : 05 34 52 34 01 Imprim en Allemagne - PRINTED in Germany Dpt lgal : parution, N ISSN : 1291-78 34 Commission paritaire : K78 976 Priodicit : Mensuel Prix de vente : 7,50

La rdaction nest pas responsable des textes, illustrations et photos qui lui sont communiqus par leurs auteurs. La reproduction totale ou partielle des articles publis dans GNU/Linux Magazine France est interdite sans accord crit de la socit Les ditions Diamond. Sauf accord particulier, les manuscrits, photos et dessins adresss GNU/Linux Magazine France, publis ou non, ne sont ni rendus, ni renvoys. Les indications de prix et dadresses figurant dans les pages rdactionnelles sont donnes titre dinformation, sans aucun but publicitaire. Toutes les marques cites dans ce numro sont dposes par leur propritaire respectif. Tous les logos reprsents dans le magazine sont la proprit de leur ayant droit respectif.

GNU/Linux Magazine France N 1 5 3

LAbO

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

La rception radiofrquence dfinie par logiciel


(Software Defined Radio SDR)
par J.-M Friedt & G. Goavec-Mrou

La diffusion large chelle de la communication radiofrquence dans les appareils grand public induit la disponibilit de composants aux performances compatibles avec ces modes de communication (fonctionnement de 50 2500 MHz ou plus, bandes passantes de lordre de la dizaine de MHz) et pour des prix ridiculement faibles grce la production de masse. Nous allons profiter de cette mode en prsentant lutilisation dun rcepteur de tlvision numrique - DVB bas sur le composant Elonics E4000 - dont ltage de rception savre tellement simple quil est compatible avec de nombreux modes de transmission analogique et numrique de donnes par liaison radiofrquence. Le flux de donnes brut issu du rcepteur radio est trait par des blocs implmentant les fonctionnalits les plus classiques dans le logiciel gnuradio et son interface graphique gnuradiocompanion. Nous verrons comment, au del de la simple utilisation des blocs de traitement disponibles, implmenter nos propres algorithmes de dcodage sur le flux dinformations reu du rcepteur radiofrquence. Nous nous intresserons en particulier au packet, au protocole ACARS, et aux radiomodems encodant linformation en FSK et AFSK.

1 Introduction la radio dfinie par logiciel (SDR)


La radio dfinie par logiciel - Software Defined Radio (SDR) - est une approche au traitement de donnes radiofrquences dportant un maximum de traitement sur du logiciel au lieu de dpendre du matriel [1, 2, 3, 4].

Compte tenu des frquences et du dbit dinformations mis en jeu lors des transmissions sans fil radiofrquences, il a t classiquement ncessaire de traiter un maximum dinformations par du matriel ddi, pour ne finalement quventuellement traiter par logiciel le flux dinformations rsultant, gnralement dans les frquences audibles (<100 kHz). Mentionnons parmi ces exemples les habituels rcepteurs radiofrquences FM et AM qui ne font

appel aucun logiciel, aux rcepteurs amateurs de mode numrique bass sur un modem audiofrquences (packet1), transmission dimages (SSTV par le vnrable JVFAX sous MS-DOS, des outils plus rcents tant probablement disponibles aujourdhui sous GNU/Linux) ou la rception dimages satellites que nous avions dj prsente dans ces pages [5]. Classiquement, le traitement logiciel dinformations transmises sans fil se

 ttp://www.baycom.org/~tom/ham/linux/multimon.html dcode un certain nombre de modes numriques partir des signaux sonores issus dun rcepteur radio et numriss h par carte son

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

LAbO

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

cantonne aux frquences audio du fait de la disponibilit dune carte dacquisition largement disponible - la carte son quipant pratiquement tous les ordinateurs personnels depuis une dizaine dannes et la puissance de calcul requise qui nest pas ngligeable, mme pour traiter un flux de donnes aussi lent que 100 kHz. En effet, le dbit du traitement de linformation est impos par le flux entrant, et toute interruption (par exemple pour grer une autre tche dvolue au systme dexploitation) se traduit par une perte irrmdiable de donnes. Aucun des systmes dexploitation grand public nayant de prtention de latence borne (temps rel), et surtout pas GNU/Linux dans sa version de base, la disponibilit dune puissance de calcul surdimensionne est la seule garantie dun traitement sans pertes dinformations. La limitation sur les interfaces dacquisitions a en partie chang avec lavnement des cartes dacquisition vido : capables dchantillonner plusieurs millions de mesures par seconde, le flux de donnes devient compatible avec lanalyse par logiciel dune bande de frquences de plusieurs MHz de large. Cependant, ltage le plus amont de traitement de linformation radiofrquence - amplificateur et transposition vers une frquence acceptable par un convertisseur analogique-numrique - reste matriel. Rcemment, un rcepteur de tlvision numrique terrestre sous forme de cl USB a induit une explosion dactivit dans le domaine de la SDR libre lorsquil sest avr que le flux de donnes fourni au logiciel de dcodage vido tait gnraliste (nous dvelopperons plus loin le flux de donnes I/Q fourni par cette interface matrielle) : pourquoi donc se limiter aux bandes de tlvision et ne pas sonder nimporte quelle bande de frquence accessible par ltage radiofrquence, et ce en vue den interprter les informations par traitement logiciel de linformation ?
2 3 4

Dans ce but, un environnement logiciel sympathique est gnuradio2, qui fournit un certain nombre de blocs de traitement de base qui permettent de rapidement apprhender le problme. La squence danalyse que nous proposons commence par une brve prsentation du matriel utilis, avant dexploiter directement quelques blocs de traitement du signal disponibles sous gnuradio en sappuyant pour la construction des applications sur son interface graphique, gnuradio-companion3. Lutilisation de blocs existants ntant d peu prs aucun intrt technique pour le dveloppeur, autre que pour un aspect ludique, nous nous attellerons ensuite la tche de traiter un flux de donnes inconnu, savoir le flux de donnes issu dun radiomodem dune part, et dautre part le flux de donnes mis par les avions suivant le protocole ACARS. Finalement, nous verrons comment remplacer le post-traitement des informations acquises pour en extraire les donnes numriques, par un traitement en temps rel sous forme de bloc compatible avec gnuradio-companion.

rfrence uhd nous seront inutiles dans la suite de cette discussion. En effet, alors que les USRP ont pu voir le jour grce la chute vertigineuse des cots de composants radiofrquences dvelopps notamment pour les applications de communication numrique sans fil (synthtiseurs de frquence, modulateur et dmodulateur I/Q sur des bandes allant de quelques MHz aux GHz, notamment par Analog Devices, Maxim ou Semtech), cette tendance sacclre aujourdhui avec lavnement de circuits compacts regroupant tous les lments radiofrquences analogiques (front end) habituellement spars en lments discrets. En particulier, un nouveau composant, le Elonics E4000 (rcepteur radiofrquence direct - sans exploitation dune frquence intermdiaire - fonctionnant de 64 1700 MHz) a t la source dune explosion de circuits trs faible cot pour la SDR. Ce composant se limite en effet amplifier le signal radiofrquence reu par une antenne, le mlanger avec un oscillateur local pour transposer la frquence5 suivi de filtres passe-bas pour ne conserver que la composante basse-frquence. Ce composant analogique fournit donc les composantes I et Q (identit et en quadrature) sur une bande passante allant jusqu 8 MHz. Ce signal analogique doit ensuite tre numris pour traitement par un ordinateur personnel. Un premier projet exploite un convertisseur analogiquenumrique de carte audio : Funcube6. Les faibles volumes de production induisent un cot de lordre de la centaine deuros, pour un dispositif la sensibilit acceptable pour de la rception de sources en orbite terrestre (satellites), mais avec une bande passante rduite aux performances dune carte son, donc une centaine de kHz.

2 Prsentation du matriel
Historiquement, le dveloppement de SDR sur plateforme libre sest organis autour des systmes USRP (Universal Software Radio Peripheral) dvelopps par Ettus Research4. Bien que de cot raisonnable en comparaison des systmes professionnels proposs, linvestissement de lordre du millier deuros reste nanmoins cantonn lamateur motiv qui a besoin des performances de tels dispositifs ddis (bande passante importante, sensibilit). Les USRP sont supportes dans gnuradio au travers des pilotes gr-uhd (UHD signifiant USRP Hardware Driver). Ce point est utile mentionner car tous les outils faisant

gnuradio.org http://www.joshknows.com/grc http://www.ettus.com/ nous avions dj expos dans ces pages le principe du mlangeur qui transpose une frquence incidente f et une frquence de rfrence f0 pour gnrer f+/- f 0, la composante somme des frquences tant limine par un filtre passe-bas. http://tetra.osmocom.org/trac/wiki/Funcube_Dongle et http://www.funcubedongle.com/

5

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Afin de pallier cette carence sur la bande passante, un projet introduisant un FPGA pour acclrer la frquence dchantillonnage a t engag sous le nom de OsmoSDR7, avec la participation de dveloppeurs aussi clbres que Harald Welte8, garantie de srieux du projet. Les dveloppements logiciels autour de ce projet ont finalement profit de la commercialisation de rcepteurs de tlvision numrique terrestre de qualit mdiocre, mais dont les volumes de production induisent des cots dachat imbattables. En effet, le portage V4L de ces cls USB de rception de tlvision a fait apparatre que tout le dcodage du flux de donnes se fait de faon logicielle (un triste rappel des modems dil y a une quinzaine dannes, aussi nomms winmodems, qui avaient engag cette tendance de rduction du matriel en transposant le dcodage au logiciel - modems inutilisables dans un environnement libre en labsence des pilotes appropris9) et que ce flux de donnes I/Q serait appropri pour des applications bien plus intressantes que la visualisation dmissions de tlvision. Il est donc dsormais possible de se lancer dans le domaine fantastique de la SDR pour un investissement matriel infrieur 20 euros : nous avons pour notre part expriment avec des cls EZCAP (DVB-T/DAB/FM) telles que (par exemple) disponibles http:// www.dealextreme.com/p/mini-dvb-tdigital-tv-usb-2-0-dongle-with-fm-dabremote-controller-92096 ou https:// www.cosycave.co.uk/product.php?id_ product=104 pour les sources que nous avons testes (pourquoi un vendeur de plantes prtendues thrapeutiques vend des rcepteurs de tlvision ? Mystre, lappt du gain na pas de limites). Le projet exploitant le convertisseur analogique-numrique embarqu sur ces cls, le Realtek RTL2832U, est issu de OsmoSDR et dcrit http://sdr. osmocom.org/trac/wiki/rtl-sdr.

2.1 Installation des outils gnuradio


Lenvironnement gnuradio est dynamique et en particulier les outils autour des cls USB pour rception de tlvision numrique changent rapidement. Il est donc de bon ton de recompiler ses outils depuis les dernires versions des sources. Ce processus a t automatis dans un script fort utile, disponible http://www.sbrac.org/files/build-gnuradio. Il est cependant significatif de raliser un aspect quelque peu surprenant de la compilation de gnuradio : au lieu dimposer les dpendances ncessaires un ensemble de fonctionnalits, linclusion ou lexclusion de morceaux de gnuradio est induite par une recherche des bibliothques disponibles. Ainsi, une premire compilation se traduit par lexclusion d peu prs toutes les fonctionnalits de gnuradio, et ce nest quen installant petit petit les bibliothques ncessaires (libfftw3-dev, modules Python) que nous finirons par atteindre lobjectif de compiler tous les modules, sauf uhd, qui ne sera pas ncessaire. En particulier, il est fondamental de compiler la partie gnuradio-companion,

une interface graphique pour accder aux modules de traitement du signal, dont nous ferons intensivement usage dans la suite de ce document.

2.2 Utilisation en oscilloscope du RTL2832U


Ayant install les outils gnuradio et en particulier gnuradio-companion, nous pouvons prendre en main une cl USB de rception de tlvision numrique terrestre EZCAP. Le premier constat est que le connecteur de type antenne de tlvision 75 ohm est peu prs inexploitable avec des antennes de radioamateur ou mme pour nos propres exprimentations dantennes ddies diverses bandes de frquences, donc nous commenons par le remplacer par une embase BNC. Afin de bien matriser la distinction entre les fonctions du composant analogique E4000 et du convertisseur analogique-numrique suivi de communication numrique RTL2832U, nous allons injecter un signal sinusodal sur ce qui apparat lvidence sur la carte lectronique comme les signaux balancs

Figure 1 : Utilisation dun rcepteur de tlvision numrique terrestre comme oscilloscope avec une bande passante de plus de 2 MHz.

7 8 9

sdr.osmocom.org https://har2009.org/program/speakers/253.en.html http://en.wikipedia.org/wiki/Softmodem

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

LAbO

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

des composantes I et Q (i.e. I+ et I- ainsi que Q+ et Q-). Ce faisant, nous gnrons le graphique de traitement du signal gnuradio le plus simple possible : une source de donnes sous la forme du bloc OsmoSDR Source (accessible dans le menu des fonctions OsmoSDR droite de gnuradio-companion) - labsence de ce menu indique que la compilation des outils ne sest pas faite convenablement - et un puits de donnes sous la forme dun oscilloscope accessible dans le menu WX GUI Widget (bloc WX GUI Scope Sink). Nous constatons sur la Figure 1 que les voies I et Q prsentent bien un signal sinusodal, en accord avec la forme du signal inject, une frquence de 200 kHz et chantillonn 2 MS/s (10 points/priode). Lhorloge interne au convertisseur EZCAP et le quartz cadenant le synthtiseur de frquence sont synchroniss mieux que 2 parties par million (2 ppm) puisque nous avons d programmer la frquence de 199999,720 Hz pour que lchantillonnage fasse exactement 10 points/priode 2 MS/s (en labsence de dclenchement sur un front, cette condition sobserve visuellement sur la sortie oscilloscope de gnuradio lorsque la sinusode arrte de se dplacer horizontalement une vitesse gale linverse de la diffrence des frquences), un rsultat impressionnant compte tenu de la simplicit du montage nexploitant quun quartz de qualit commerciale pour cadencer llectronique numrique. Nous avons mentionn un gain dun facteur de lordre de 2,5*106/48000 50 sur la frquence dchantillonnage en exploitant le RTL2832U comme carte dacquisition la place dune carte son. Cependant, ce chiffre ne doit pas cacher la dynamique mdiocre du convertisseur analogique-numrique de ce composant qui ne code linformation que sur 8 bits. Une dynamique de 20*log10(28)=48 dB est mdiocre compte tenu de la dynamique des signaux radiofrquences acquis qui atteint souvent 60 dB. Un tage de pramplification capable de sadapter la puissance radiofrquence

reue est donc souhaitable (ajustement automatique par le E4000 ou de faon logicielle en ajustant manuellement le gain de ce composant). Le sur-chantillonnage dun facteur 50 ne compense pas la mdiocrit de la rsolution des convertisseurs par rapport ceux dune carte son. En effet, il est bien connu [6] quen appliquant une moyenne glissante sur N points acquis, lcart type sur ces mesures (supposes polues par un bruit uniforme) dcrot comme N. Ainsi, il faut quadrupler la frquence dchantillonnage pour diviser par 2 le bruit sur le signal acquis et donc ajouter un bit sur la rsolution du convertisseur analogique-numrique. La rfrence [6] formalise ce point en notant que pour une frquence dchantillonnage fse, le gain en rsolution (p bits) par application dune moyenne glissante par rapport aux acquisitions frquence fe est

3 Premiers pas : utilisation avec gnuradio-companion


Nos essais de rception radiofrquence ont pour ambition de recevoir des signaux plus faibles que les missions commerciales sur bande FM. En particulier, nous nous intresserons la rception dimages mises par des satellites sur des frquences autour de 137 MHz. Il savre que la majorit des frquences qui vont nous intresser dans ce document se situent autour de cette valeur - 88 108 MHz pour la FM commerciale, 108 137 MHz pour la bande arienne, 154 MHz pour le packet radio - et nous exploiterons donc dans tous ces cas une antenne diple ajuste pour 137 MHz. Afin de maintenir la portabilit dun rcepteur radiofrquence se branchant sur port USB, lantenne se doit dtre dmontable et tenir dans un sac dos. Pour ce faire, un tube de cuivre creux de 8 mm de diamtre est coup en deux morceaux de 55 cm de longueur (300/137/4 0,55 avec 300 m/s la clrit dune onde lectromagntique et 137 la frquence dintrt en MHz) et munis, chaque extrmit, de fiches banane de 4 mm de diamtre. Ce montage robuste sassemble facilement sur un support en plastique muni de deux embases 4 mm femelles auxquelles est soud un bout - aussi court que possible - de cble coaxial RG58 muni une extrmit dune fiche BNC (Fig. 2). Exceptionnellement, nous ajouterons un amplificateur faible bruit Hittite HMC478 (alimentation en 5 V, facteur de bruit 2 dB) entre lantenne et le rcepteur EZCAP, bien que le gain dun tel montage reste dmontrer. Le pr-amplificateur faible bruit (LNA) est aliment en 5 V par un second port USB. Dans le cas particulier de lADS-B qui occupe une bande de frquences autour de 1090 MHz, une antenne discone large bande a t exploite (Diamond Antenna D190, annonce comme fonctionnelle entre 100 et 1500 MHz) (Fig. 2).

ou, en passant en chelle logarithmique, 10log10(fse/fe)=10log10(4)*p soit, en notant que 10log10(4)6, nous retrouvons [3] que le gain en rsolution en bits p pour un sur-chantillonnage de fse/fe est 1/6*10log10(fse/fe). Dans tous les cas, nous sommes loin datteindre les 16 bits de rsolution dune carte son, puisque 10log10(50)/63 soit un total de 11 bits sur le convertisseur quivalent fonctionnant la mme frquence que la carte son. Ce rapide petit calcul nous incite nous rappeler que la frquence dchantillonnage nest pas ncessairement la caractristique principale dun convertisseur analogique-numrique, et dans ce cas les plus de 2 Mchantillons/s ne se justifient que pour analyser un signal de bande passante importante, mais de dynamique rduite. Si la bande passante ne se justifie pas, une carte son sera plus efficace pour chantillonner des signaux avec une dynamique accrue. Tous ces traitements se font sur un eeePC701 et ne ncessitent donc pas des ressources normes en termes de puissance de calcul ou de mmoire.

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Figure 2 : Deux montages dantennes exploits avec le rcepteur EZCAP : une antenne diple facilement dmontable pour les bandes de frquences autour de 137 MHz, et sinon une antenne discone large bande. Aussi importante que la nature de lantenne, lemplacement slectionn doit tre aussi libre que possible dobstacles. Ici, un balcon au 3me tage dun btiment orient vers lEst est acceptable pour la rception FM et davions, mais insuffisamment dgag pour la rception dimages issues de satellites.

3.1 La bande FM commerciale


Le test le plus simple car permettant de recevoir un signal mis en continu avec une forte puissance est la bande FM commerciale, entre 88 et 108 MHz. Cette bande de frquences est qualifie de large bande ( Wide FM) du fait de lencombrement spectral important occup par chaque station (180 kHz). Les canaux allous aux radios sont donc spars denviron 200 kHz [9, p.138]. Ce test fera office de validation du bon fonctionnement de linstallation : interface graphique gnuradio-companion, source OsmoSDR (comme utilise auparavant pour lexemple de loscilloscope), dmodulation par le bloc WFM et puits de donnes sous forme de la carte son dune part (aprs dmodulation) et analyse du spectre acquis (avant dmodulation) pour identifier la frquence dmission des stations dautre part. Cet exemple fournit lopportunit dintroduire une premire contrainte sur lassemblage des blocs de traitement : il nous faut garantir la continuit du flux

Figure 3 : Exemple de chanes de traitement pour le dcodage de la bande FM commerciale (88-108 MHz) ou la bande daviation o les communications se font en AM (au-dessus de la bande FM commerciale, 108-137 MHz). Le mode de dmodulation FM troite na pas fourni de rsultat significativement diffrent du dmodulateur WFM, mais est inclus pour illustrer la dcimation en sortie de ce dmodulateur par une fonction qui ne garde que 1 chantillon sur 4 (et donc fournit le flux de donnes au dbit appropri la carte son). Le spectre, en bas droite, du signal acquis, prsente une extension de -fe/2 fe/2 avec fe=1152 kHz la frquence dchantillonnage : nous y trouvons videmment un pic autour de la frquence de la chane radio coute (100,4 MHz) ainsi quun pic autour de la frquence adjacente (100.9 MHz), qui ninterfre nanmoins pas avec la dmodulation grce au filtre passe-bas situ aprs lanalyseur de spectres.

de donnes le long de la chane de traitement, et donc ne pas fournir trop de donnes un bloc qui ne peut tout traiter, ni faire attendre un bloc qui naura plus rien faire. Ainsi, dans lexemple de la Figure 3, si nous partons de la fin de la chane de traitement (le puits quest la carte son du PC), nous devons fournir un flux continu de donnes la frquence dchantillonnage choisie 48 kHz. Nous constatons que le bloc de dmodulation FM large bande (WFM) effectue une dcimation dun facteur 4 (i.e. sort 4 fois moins de donnes quil en reoit), donc le flux de donnes en entre de ce bloc doit tre 4*48=192 kHz. Le filtre passe bas effectue quant lui une dcimation dun facteur 6, donc ncessite un flux en entre de 192*6=1152 kHz, qui est bien la valeur que nous observons dans le sampling rate de ce bloc. La source OsmoSDR tant directement connecte au filtre passebas, sa frquence dchantillonnage

est elle aussi slectionne 1152 kS/s. On notera quune limitation de la source OsmoSDR est de ne pas pouvoir descendre sous quelques centaines de kHz de frquence dchantillonnage : on conservera donc habituellement une source chantillonnant entre 1 et 2,5 MS/s, quitte dcimer par un filtre passe-bas si la suite des tapes ne ncessitent que des traitements sur des bandes passantes rduites. Le lecteur est encourag changer les frquences dchantillonnage ou facteurs de dcimations sur un tel graphique pour apprhender leffet derreurs sur ces valeurs. Une extension propose dans le cadre de gnuradio-companion est le dcodage de linformation RDS (Radio Data System)10 qui fournit une information sous forme numrique sur la station coute (nom de la station, frquences correspondantes aux alentours, nature du programme transmis, ventuellement information de trafic, ...). Cet exemple est intressant car il illustre

10

https://cgran.org/wiki/RDS : noter que, apparemment, pour un dysfonctionnement de loption -fvar-tracking-assignement des versions rcentes de GCC, nous avons t obligs de dsactiver les options -g -O2 de la compilation (i.e. rester en -O0), faute de quoi la compilation choue aprs avoir occup toute la mmoire disponible.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

LAbO

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

la souplesse du dcodage dinformations transmises sur porteuse radiofrquence par logiciel. En effet, le mme flux de donnes est dune part dmodul en un flux audible, et dautre part en un flux de donnes numriques, sans que le matriel nait t modifi (Fig. 4). Par ailleurs, notons que lauteur a recr un rcepteur FM comme nous le ferions base de composants lectroniques analogiques, en asservissant une boucle verrouille en phase (PLL) sur la sortie filtre en passe-bas du rcepteur radio, au lieu dutiliser le bloc de dmodulation prt lemploi de gnuradio-companion. Les divers filtres passe-bande permettent ensuite de slectionner la nature de linformation traite dans les diverses bandes de frquence audio (son ou RDS). Ci-dessous, quelques exemples de captures des signaux numriques transmis dans la bande FM commerciale ct des signaux analogiques radiofrquences audibles, illustrant quelques-uns des messages transmis sur ce mode de communication.
00A (BASIC) - PI:F211 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:17) ==> RTL <== -TP- -Music-STEREO - AF: 00A (BASIC) - PI:F211 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:17) ==> RTL <== -TP- -Music-STEREO - AF: 00A (BASIC) - PI:F211 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:17) ==> RTL <== -TP- -Music-STEREO - AF:104.00MHz 00A (BASIC) - PI:F211 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:17) ==> RTL <== -TP- -Music-STEREO - AF:92.40MHz, 93.90MHz 00A (BASIC) - PI:F211 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:17) ==> RTL <== -TP- -Music-STEREO - AF:95.00MHz, 97.50MHz 00A (BASIC) - PI:F211 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:17) ==> RTL <== -TP- -Music-STEREO - AF:101.20MHz, 101.50MHz 00A (BASIC) - PI:F211 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:17) ==> RTL <== -TP- -Music-STEREO - AF:102.20MHz, 103.20MHz 00A (BASIC) - PI:F211 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:17) @@@@@ Lost Sync (Got 46 bad blocks on 50 total) @@@@@ Sync State Detected @@@@@ Lost Sync (Got 46 bad blocks on 50 total) @@@@@ Sync State Detected 00A (BASIC) - PI:F219 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:25) ==> IRL <== -TP- -Music-STEREO - AF:99.60MHz, 99.80MHz 00A (BASIC) - PI:F219 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:25) ==> IRL <== -TP- -Music-STEREO - AF:99.60MHz, 99.80MHz 00A (BASIC) - PI:F219 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:25) ==> IRL N <== -TP- -Music-STEREO - AF:97.80MHz, 98.40MHz 00A (BASIC) - PI:F219 - PTY:None (country:EG/FR/NO/BY/BA, area:National, program:25) ==> VIRL N <== -TP- -Music-STEREO - AF:100.40MHz @@@@@ Lost Sync (Got 47 bad blocks on 50 total) @@@@@ Sync State Detected @@@@@ Lost Sync (Got 49 bad blocks on 50 total) @@@@@ Sync State Detected 00A (BASIC) - PI:FC67 - PTY:None (country:EG/FR/NO/BY/BA, area:Regional 9, program:103) ==> GRAY <== -TP- -Music-STEREO - AF:100.10MHz 00A (BASIC) - PI:FC67 - PTY:None (country:EG/FR/NO/BY/BA, area:Regional 9, program:103) ==> GRAY <== -TP- -Music-STEREO - AF:97.10MHz 02A (RT) - PI:FC67 - PTY:None (country:EG/FR/NO/BY/BA, area:Regional 9, program:103) Radio Text A: RADIO STAR TOUS LES HITS BESANCON 106.6 GRAY 100.2 00A (BASIC) - PI:FC67 - PTY:None (country:EG/FR/NO/BY/BA, area:Regional 9, program:103) ==> 10AY <== -TP- -Music-STEREO - AF:100.70MHz, 87.80MHz

04A (CT) - PI:F221 - PTY:None (country:EG/ FR/NO/BY/BA, area:National, program:33) Clocktime: 10.08.2012, 17:27 (+2.0h) 02A (RT) - PI:F221 - PTY:None (country:EG/ FR/NO/BY/BA, area:National, program:33) Radio Text A: Mozart : Concerto pour piano n 14:1er mvt

3.2 ADS-B
ADS-B (Automatic Dependent Surveillance-Broadcast) est un protocole numrique de communication entre un avion et le sol initi sur une requte provenant dun RADAR qui sollicite une information de position dun aronef suppos tre quip dun rcepteur GPS. Depuis le sol, un rcepteur (nous) ne peut entendre que la rponse de lavion la sollicitation : cette rponse se fait la frquence de 1090 MHz. Ainsi, ADS-B fournit une information complmentaire lanalyse purement passive de rflexion de londe lectromagntique par lavion : au lieu de se contenter du temps de vol et orientation de lantenne au moment de lmission de limpulsion lectromagntique, la position de lavion est complte par sa localisation GPS. Ce protocole a t implment sous forme de script gnr par gnuradio, disponible https://www.cgran.org/ wiki/gr-air-modes et dcrit en dtail dans les transparents [10]. La mise en commun des informations acquises par de tels rcepteurs dADS-B permet de cartographier la position des avions dans le monde de faon indpendante des contrleurs ariens, tel que par exemple disponible http://www. radarvirtuel.com/. Le logiciel propos par N. Foster pour gnuradio inclut une sortie au format KML compatible avec Google Earth et Google Maps (Fig. 5).

Les trames que nous avons slectionnes illustrent dune part les champs de type AF (alternative frequencies) grce auxquels un rcepteur radio sait comment rechercher un nouveau canal pour le mme programme radiophonique une fois la liaison courante trop faible, et dautre part le champ RT (radio text) dans lequel un texte libre dau plus 64 caractres est transmis. Nous navons pas eu loccasion de tester TA (traffic announcement) qui est probablement une des applications les plus utiles de ce mode de communication numrique sur la bande FM commerciale. Un dernier exemple propose le transfert dheure (champ CT) par RDS ainsi que lutilisation du champ de texte libre (RT) pour annoncer le titre en cours de diffusion :
11 12 13 14

3.3 Satellites
Deux essais sur les satellites en orbite basse polaire de la NOAA11 et sur la station spatiale internationale (ISS) se sont rvls sans succs, probablement par manque de sensibilit du rcepteur.

http://rof.li/pic/groundplane/ http://www.oz9aec.net/index.php/gnu-radio/gnu-radio-blog/477-noaa-apt-reception-with-gqrx-and-rtlsdr https://cgran.org http://gnuradio.org/redmine/projects/gnuradio/wiki/OutOfTreeModules

10

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Lajout dun amplificateur faible bruit de 25 dB nayant pas amlior la situation, il nest pas exclu que les rglages naient t mauvais. En particulier, une mise jour rcente du pilote du convertisseur analogique-numrique permet de dsactiver le contrle de gain automatique, qui semble tre un handicap significatif pour la rception de signaux faibles12.

4 Dcodage dun mode numrique


Lutilisation de fonctionnalits existantes nest que dun intrt limit et le dveloppeur se lasse vite dutiliser les modules disponibles sur le dpt des projets associs gnuradio CGRAN13. Notre vritable intrt consiste en la matrise des mthodes de dmodulation en vue dadapter ces techniques des mthodes qui ne sont pas encore implmentes, et ainsi utiliser loutil open source quest gnuradio comme un outil de prototypage souple. Laspect open source du projet est fondamental pour apprendre par la lecture des codes dautrui14. Nous allons proposer daborder 3 modes de communication numriques : la FSK des radiomodems, lAFSK tel quutilis en packet radio amateur ou commercial, et le protocole ACARS de communication des avions civils (et militaires par compatibilit avec le rseau civil), protocole plus ancien mais plus intressant que lADS-B puisque transportant des messages sur ltat de laronef ou des messages de lquipage vers le sol.

Figure 4 : Haut : capture dcran du dcodeur RDS en fonctionnement. Noter dans le terminal, en bas de la fentre, les messages qui saffichent (les mme messages saffichent dans le terminal do a t lanc gnuradio-companion), et dans le menu de droite les fonctions RDS qui ont t ajoutes aprs compilation des blocs disponibles https://cgran.org/wiki/RDS. Bas : schma complet issu de http://mmbtools.crc.ca/content/view/45/73/#fm_rds_rx mais pur de quelques sorties graphiques qui consommaient trop de ressources de calcul sur eeePC 701.

Figure 5 : Gauche : spectre acquis lors de lcoute de transmissions en ADS-B, avec une frquence centrale lgrement dcale par rapport la frquence dintrt. Droite : carte des avions suivis depuis un rcepteur situ prs dOrlans, avec une antenne situe sur un balcon dgag vers lEst uniquement.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

11

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

LAbO

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Bien que tous ces modes aient t conus dans des dbits de donnes compatibles avec les cartes son, la solution de rcepteur de tlvision numrique terrestre (DVB) offre nanmoins une solution intgre qui vite lachat dun scanner radiofrquence. Bien quun scanner soit un outil souple demploi et bien plus sensible quune cl USB, son cot peut paratre rdhibitoire pour lamateur dsireux de sengager dans la voie du dcodage de modes numriques sans vouloir effectuer un investissement financier consquent. Par ailleurs, le dcodage numrique des signaux par logiciel permet de dynamiquement adapter les caractristiques des filtres en ntant limit que par la puissance de calcul disponible, alors quun scanner noffre quun nombre fini de modes de dcodage et gnralement 2 ou 3 largeurs de filtres, implments sous forme matriel et donc inaccessibles pour lacheteur de linstrument.

de ces modulations a des proprits dencombrement spectral, de robustesse diverses sources de bruit et de simplicit de mise en uvre qui impliquent un choix contraint par les paramtres de communication recherchs. Un cas particulier que nous aborderons plus bas est lAFSK - Audio Frequency Shift Keying - dans lequel les signaux ne sont pas cods par une frquence ou une phase, mais par une modulation en frquence audible de la porteuse radiofrquence. Il sagit dun mode dvelopp spcifiquement pour lutilisation avec des modes de communication de la voix (tlphonie dans le cas des modems, ou transceivers radiofrquences) qui ne ncessitent pas que la sortie soit adapte pour des gammes de frquences autres que les bandes de frquences audibles (typiquement 1000-5000 Hz). Ayant introduit ces concepts, nous constatons que le dcodage de signaux numriques consiste en lextraction dun de ces paramtres pour en tracer lvolution dans le temps et par consquent remonter aux signaux transmis. Le cas de lASK est le plus simple : nous calons le rcepteur sur la frquence de la porteuse (ventuellement avec un asservissement pour garantir que la drive entre oscillateur de lmetteur et du rcepteur soit compense), et un filtre passe-bas dtecte lenveloppe du signal. Lamplitude du signal traduit alors la valeur du bit transmis. La FSK est peine plus complique dans le principe puisque nous exploitons le signal de contrle de loscillateur local asservi par verrouillage de phase sur le signal reu, mais son exploitation est rendue triviale par la disponibilit sous gnuradio-companion du bloc Modulators WBFM receive. La dmodulation dun signal passe dans un premier temps par la gnration des signaux I (In-phase) et Q (quadrature) que nous avons dj mentionns sans les dfinir (Fig. 6) : il sagit du mlange du signal incident (dit RF - RadioFrequency) avec un oscillateur local de rfrence (dit LO - Local Oscillator) en vue de gnrer I=A(t)sin((RF-LO)*t) et Q=A(t)cos((RFLO)*t). Alors I+j*Q=A(t)exp( j*2**(RFLO)*t) avec j2=-1 [12] (noter que sin et cos sont

Figure 6 : Principe de la dmodulation IQ pour extraire les deux grandeurs reprsentatives dun signal dentre radiofrquence s(t) connaissant sa frquence f (ou pulsation angulaire =2 f), savoir son amplitude A(t) et sa phase (t), toutes deux pouvant tre utilises pour coder de linformation si elles varient avec le temps t. La frquence de coupure des deux filtres passe-bas aprs les mlangeurs dfinissent la bande passante du dtecteur (qui dfinit en partie le dbit de communication puisquil sagit de la vitesse laquelle les symboles dtermins par A(t) et/ou (t) peuvent varier).

4.1 Les modes de modulation et traitement numrique du signal


Nous ne pouvons prtendre introduire ici tous les lments de traitement du signal associs aux modulations sur porteuse radiofrquence en vue de transmettre un signal. Afin de faciliter lintroduction aux concepts pour le lecteur qui nest pas familier avec ces notions, rappelons quun signal priodique s(t) est caractris pour son comportement temporel t par trois grandeurs : son amplitude A, sa frquence f et sa phase selon s(t)=A(t)*sin(2 f(t)+(t)). Ces trois grandeurs peuvent voluer dans le temps, individuellement ou simultanment, pour coder un signal transmis : A(t) implique une modulation damplitude (AM en analogique, ou ASK - Amplitude Shift Keying pour les modes numriques), f(t) implique une modulation de frquence (FM en analogique, ou FSK - Frequency Shift Keying - pour les modes numriques) et (t) implique une modulation de phase (PSK - Phase Shift Keying) [11]. Chacune

spars par un dphasage de 90o, donc en pratique les schmas de dmodulateur I/Q indiquent ces oprations par un mlangeur, donc la composante LO a t sur une des voies dphase de 90o). Ces deux signaux sont fournis par le composant Elonics E4000 aprs que lutilisateur ait configur LO. Dans ces conditions, une reprsentation simple des concepts de modulation que nous venons de citer est rsume dans le diagramme de constellation [12, p.11]. Ce diagramme trace en abscisse la composante I et en ordonne la composante Q telles que nous venons de les dfinir et nous permet de revenir au plan complexe dont les proprits sont bien connues : la distance dun point lorigine reprsente le module du complexe (dans notre cas A(t)) et langle entre laxe des abscisses (I) et le point reprsent dans le plan complexe reprsente sa phase (t). Ainsi, un diagramme de constellation reprsente dans le plan complexe (I, Q) les divers codes possibles. Une modulation en phase se traduit par des points distribus le long dun cercle de rayon constant centr sur lorigine, tandis quune modulation en amplitude se traduit par des points distance variable de lorigine. La modulation en frquence est un peu particulire puisque

14

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

packet radio met des signaux moduls par des frquences audibles, et le protocole de communication avec les avions ACARS module un signal en amplitude.

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

4.2 Cas de la FSK du Semtech XE1203F


Le radiomodem XE1203F15 de Semtech est un transceiver half duplex (soit il met, soit il reoit) susceptible de moduler un oscillateur en frquence (FSK) pour coder les deux tats possibles de la donne numrique transmise. La frquence de sa porteuse est programmable par pas de 500 Hz : nous slectionnons 434 MHz, en plein milieu de la bande Industrielle, Scientifique et Mdicale (ISM). Lexcursion de la modulation FM entre les deux tats est programmable - nous choisissons 55 kHz, et le dbit des informations est dfini par le flux de donnes issu de linterface asynchrone (UART) du microcontrleur (dans notre cas un ST STM32F103) connect aux broches DATA et DATAIN du radiomodem (flux de donnes numriques transmis). Ces connexions de broches semblent tre le mode de communication le plus simple entre le radiomodem XE1203F et le bus de communication asynchrone (RS232) dun microcontrleur, bien que les bits de dbut (start) et de fin (stop) de communication introduisent quelques subtilits dans linterprtation quen fait le radiomodem. Lapplication du dmodulateur WFM (qui est appropri pour une excursion aussi importante que 55 kHz) donne le signal de la Figure 7 : nous observons de faon vidente des transitions reprsentatives du flux de donnes sur loscilloscope connect en sortie de dmodulateur. La FSK ne ncessite aucun autre traitement particulier pour retrouver les valeurs des bits puisque loscillateur radiofrquence est directement attaqu par la valeur du signal numrique transmis : le dmodulateur fournit un signal basse frquence proportionnel au signal derreur de la boucle asservie en phase, donc directement une tension proportionnelle la frquence codant chaque bit.

Figure 7 : Haut : schma blocs pour dcoder le flux dinformations transmis par un radiomodem en FSK (il sagit du mme bloc de WFM que nous avions dj utilis pour les bandes FM commerciales). Bas : sortie oscilloscope au cours de lenregistrement. Les deux tats de transmission des donnes sont dj clairement visibles et laissent prsager dun dcodage ais.

la frquence est la drive de la phase et par consquent les points dans le plan complexe tournent sur un cercle centr sur lorigine. Nous allons, dans les sections qui vont suivre, illustrer le dcodage de ces modes de modulation sur des exemples concrets mis en uvre sur des metteurs commercialement disponibles dont nous dsirons dcoder les informations transmises. Le radiomodem XE1203F de Semtech met sur un codage modul en frquence, le

15

http://www.semtech.com/apps/filedown/down.php?file=xe1203f.pdf

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

15

LAbO

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Par ailleurs, lintervalle de temps entre deux transitions est en accord avec un dbit de 4800 bits/s. Enfin, lanalyse de ces donnes pour en extraire une squence comprhensible ncessite de sapproprier la squence dmission que nous avons implmente dans le microcontrleur selon les consignes de la fiche de donnes de Semtech : 1.  La transmission commence par une squence doscillations entre 0 et 1 nomme bit synchronizer pour que le rcepteur cale son oscillateur sur le signal mis. Compte tenu du 0 en start bit et 1 en stop bit, nous constatons quune alternance de 0 et de 1 sobtient en envoyant la valeur 0x55 (le bit de poids le plus faible est envoy en premier), i.e. le caractre U. 2.  Nous utilisons la fonctionnalit de coder une adresse du radiomodem metteur, notamment aprs avoir constat que le bruit radiofrquence ambiant a tendance tre dtect comme une transmission errone en labsence de cette fonctionnalit (Pattern recognition block). 3.  Finalement, le motif didentification ayant t dtect, le message lui-mme est transmis. Nous vrifions pour chaque octet dcod que le dernier bit (stop bit) est 1, sinon nous indiquons une erreur. Cette vrification permet en partie de saffranchir du bruit sur le canal radiofrquence de transmission qui risquerait de nous laisser croire quun start bit sest dclench (transition de 1 0), bruit qui a peu de chances de se retrouver au niveau du stop bit en labsence dune vraie transmission de donnes. Afin de faciliter le dveloppement du dcodage, la stratgie de dveloppement que nous proposons consiste systmatiquement commencer par enregistrer dans un fichier binaire (ou WAV pour y ajouter un en-tte de format incluant taille des donnes et frquence dchantillonnage) un flux de donnes, y appliquer dans un

premier temps un algorithme de traitement dvelopp sous GNU/Octave, avant de le traduire en C pour inclure cet algorithme dans le formalisme de gnuradio (section 5) avant de finalement appliquer un vrai flux de donnes issu du rcepteur radio. La Figure 8 propose un exemple de schma bloc pour valider lenregistrement et afficher en mode oscilloscope les valeurs stockes dans un fichier binaire (nous avons toujours exploit le mode par dfaut dun enregistrement mono-voie oppos stro - en 8 bits/donnes).

Figure 8 : Bloc pour rejouer un signal enregistr dans un fichier binaire muni dune en-tte WAV : noter lutilisation du bloc throttle pour imposer le dbit dmission des donnes lues dans le fichier.

4.3 Cas de lAFSK


LAudio Frequency Shift Keying encode les deux tats possibles sur une frquence audible, typiquement entre 1000 et 1550 Hz pour un tat, et 2000 2500 Hz pour lautre. En particulier, le mode de transmission packet hrite des protocoles mis en place lpoque de la communication numrique sur lignes tlphoniques cbles analogiques au moyen de modems. Lintrt pour ce mode tient en deux aspects : dune part il sagit dun mode de communication numrique couramment utilis par les radioamateurs, et dautre part le rseau de bus Ginko de Besanon exploite des modems bass sur ce protocole de communication pour localiser ses bus (missions sur 154,150 et 154,154 MHz). Le mode le plus commun de packet radio est un codage des deux tats possible du bit par un signal 2200 et 1200 Hz (protocole Bell 202), et transmission de donnes au rythme de 1200 bits/s. Sur lexemple de la Figure 9, les ronds bleus sont chantillonns tous les 40 points, soit pour un chantillonnage 46 kS/s, un dbit dinformation de 48000/40=1200 bits/s. Comme divers protocoles de modulation sont disponibles (par exemple codage sur 1300 et 2100 Hz tel que dfini dans ITU-V.2316), nous avons choisi dappliquer des filtres large bande coupant autour de 1700 Hz, garantissant ainsi une compatibilit avec peu prs tous les cas dcrits sur le Web.

16

http://wiki.ham.fi/AFSK.en

16

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Le script GNU/Octave ci-dessous introduit les premiers pas pour le traitement des signaux enregistrs par gnuradio aprs dmodulation FM en bande troite (NFM) en vue den extraire les valeurs des bits successifs. Lapproche slectionne consiste en une paire de filtres passe-bande autour des deux frquences supposes coder les deux tats transmis, et est donc souple demploi pour sadapter diverses valeurs de frquences audio.
fe=48000; deb= 338100; fin= 488000; SEUIL=200; f=fopen(filename=120723_ginko.wav);d=fread(f,inf,uint8); d=d(deb:fin);N=fin(m)-deb(m); f=linspace(0,fe,N); d=d-mean(d);

la valeur prcdente, et un 1 (1300 Hz) la reconduction de ltat prcdent inchang. Le choix de ne prendre quun point sur 40 est impos par le dbit suppos de 1200 bits/ seconde sur des donnes chantillonnes 48 kHz.
binaire=reshape(tout(1:floor(length(tout)/8)*8),8,floor(length(tout)/8)); code_asc=binaire(:,1)+binaire(:,2)*2+binaire(:,3)*4+binaire(:,4)*8+binaire (:,5)*16+binaire(:,6)*32+binaire(:,7)*64; % +binaire(:,8)*128; printf(%02x ,code_asc); printf(\n);

Finalement, les donnes sont rorganises en paquets en faisant lhypothse dun octet pour 8 bits, et le rsultat affich sous forme dune squence de valeurs hexadcimales (%02x) ou de caractres ASCII.
14 sortie apres filtrage (u.a.) 12 10 8 6 4 2 0 9000 1000-1500 Hz 2000-2600 Hz seuillage

Initialisation des variables - en partie de la frquence dchantillonnage fe, et lecture dun segment de donnes dans un fichier enregistr par la fonction wav de gnuradiocompanion (8 bits/chantillon, une voie).
c=ones(30,1)/30; h=firls(42,[0 500 1000 1500 1900 fe/2]/fe*2,[0 0 1 1 0 0]); [H,freq]=freqz(h,1,512,fe); y12=filter(h,1,d(1:N)); yc12=conv(abs(y12),c);yc12=yc12(15:end-15);plot(yc12,c);hold on

Nous dfinissons un filtre de rponse impulsionnelle finie (FIR) dont le gabarit est dfini par les amplitudes du second vecteur pour les frquences du premier vecteur. Dans ce cas, nous laissons passer lnergie entre 1000 et 1500 Hz (amplitude de 1) et coupons en dehors de ces frquences. Un filtre numrique est toujours dfini pour des frquences normalises par rapport la frquence dchantillonnage. Finalement, aprs filtrage, un filtre passe-bas est appliqu sous forme de convolution avec une fentre rectangulaire de 30 lments de long.
h=firls(42,[0 1700 2000 2600 4600 fe/2]/fe*2,[0 0 1 1 0 0]); y24=filter(h,1,d(1:N)); yc24=conv(abs(y24),c);yc24=yc24(15:end-15);plot(yc24,m)

9500

10000 10500 11000 echantillon (48 kS/s)

11500

220.0

Figure 9 : Rsultat du dcodage, avec application de deux filtres passe-bande sur les signaux bruts issus du rcepteur radiofrquence aprs dmodulation en NFM (Narrow FM). Les bits successifs sont clairement visibles, compatibles avec un flux de donnes en 1200 bits/s.

La procdure est ritre pour un filtre passe-bande entre 2000 et 2600 Hz.
ind=[9160:40:48000]; v1=find(yc12(ind)>yc24(ind));tout(v1)=1; v2=find(yc12(ind)<=yc24(ind));tout(v2)=0; res(1)=0; for k=1:length(tout) if (tout(k)==0) res(k+1)=1-res(k); else end plot(ind,tout,o); % http://wiki.ham.fi/AFSK.en % 1300 Hz = 1 = mark % 2400 Hz = 0 = space res(k+1)=res(k);end

Lobtention de la squence de bits nest que le dbut de laventure : il faut maintenant tre capable den extraire une information pertinente, et ce en identifiant le baud rate (les protocoles associs au packet nous laissent penser quun flux de 1200 bits/s est le plus probable, en accord avec nos observations sur la Figure 9), le nombre de bits/donnes et lventuel bit de parit, et finalement la signification de chaque octet dcod. Ces points nont pas encore t lucids.

4.4 Cas de lAM et le protocole ACARS


ACARS est un protocole de communication utilis en aronautique lchelle internationale pour transfrer diverses informations au cours du vol dun aronef, que ce soit de faon automatique au cours de phases du vol bien dfinies (taxi avec des informations de type quantit dessence, en cours de vol avec par exemple lhoraire darrive prvu et des informations mtorologiques, en approche avec les portes de dbarquement et ltat des racteurs, aprs atterrissage avec le volume dessence restant, des informations sur lquipage ou des dysfonctionnements informatiques).

v1 et v2 dfinissent ltat de bit le plus probable en comparant la puissance en sortie des deux filtres passe-bande. Tel que dcrit http://n1vg.net/packet/index.php, un 0 (2400 Hz) encode un changement dtat du bit par rapport

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

17

LAbO

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

La communication numrique en Europe suivant le protocole ACARS se fait sur la frquence de 131,725 MHz, ou accessoirement sur 131,525 MHz et 131,550 MHz. Compte tenu de la bande passante de la dmodulation par gnuradio, toutes ces frquences peuvent tre analyses simultanment. Pour des raisons que nous ne saurions expliquer, toutes les communications lies laronautique sont modules en amplitude (AM). ACARS est un protocole ancien et simple dcoder, bien document dans http:// files.radioscanner.ru/files/download/file4094/acars.pdf et http://www.tapr.org/ aprsdoc/ACARS.TXT. Nous y apprenons que deux frquences encodent les deux tats binaires possibles de linformation transmise : les frquences de 1200 et 2400 Hz sont utilises pour transmettre des informations 2400 bits/seconde. Il existe peu dimplmentations libres : acarsd http://www.acarsd.org/ est gratuit mais ne diffuse pas ses sources, tandis que acarsdec http://sourceforge. net/projects/acarsdec/ puis http://www.r-36.net/src/acarsdec/ semble stre arrt ltat de prototype qui na plus volu depuis 2007 (ce qui ne retire rien son intrt pdagogique, mais lexemple fourni nest plus fonctionnel et lhbergeur actuel du code nen connat pas le fonctionnement).

Le choix des frquences de modulation (1200 et 2400 Hz) relativement au dbit (2400 bits/seconde) peut paratre surprenant tant que nous navons pas mis en uvre un dcodeur de ce protocole : la premire approche nave (que nous avons utilise suite aux exprimentations dcrites auparavant sur le packet) consiste rpartir des filtres passe-bande rponse impulsionnelle finie (FIR) et filtrer les deux bandes de 1200 et 2400 Hz. Cependant, cette approche ncessite un chantillonnage rapide du signal, car pour une frquence de 48 kHz dchantillonnage (compatible avec une sortie sur carte son), une priode de signal 2400 Hz ne comporte que 20 points, un nombre rduit pour dfinir un filtre passe-bande efficace (et notamment prsentant un coefficient nul la frquence nulle pour liminer la composante DC qui rend les seuils difficiles tablir sinon). Cette approche fonctionne, mais ne tire pas parti du choix judicieux des paramtres que nous venons de citer selon les considrations suivantes : 1.  La proportionnalit du dbit (bitrate) et des deux frquences utilises pour coder linformation garantit la continuit de la phase entre bits successifs. En effet, une fois que la porte de dcoupe des bits est synchronise sur loscillateur gnrant les signaux audio, nous sommes certains que la sinusode du signal audio passe toujours par 0 un changement de bit. 2.  L e fait de coder un bit par une demi priode audio et lautre bit par une priode complte exploite pleinement la capacit de lintercorrlation identifier la nature du bit encod. Nous allons dvelopper ce dernier point qui est au cur dun dcodeur plus efficace que la simple convolution dun filtre passe-bande sur lensemble des donnes acquises. Notons dans un premier temps les relations suivantes, qui permettent de valider que la dtection du mauvais tat dun bit se tra-

Figure 10 : Spectres dans la bande arienne de 108 137 MHz, o toute communication se fait en modulation damplitude (AM).

18

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

duit par un signal de valeur moyenne nulle (intgrale sur la longueur dun bit, soit 1/2400 s) tandis que la dtection du bon bit se traduit par une valeur moyenne non nulle et gale pour les deux valeurs de bits dtects : voir cadre ci-dessus. Pour ceux qui ont oubli leur table de trigonomtrie, il sagit dune excellente occasion de tester le site de Wolfram http://www.wolframalpha.com/ en lui demandant de calculer int_0^1 sin^2(pi*x)dx. Noter par ailleurs quil est relativement trivial dintuiter que lintgrale sur une priode dune fonction paire par une fonction impaire de valeur moyenne nulle est nulle, et que lintgrale du carr dune fonction (donc dont toutes les valeurs sont positives) est non nulle (figure de droite dans le cadre ci-dessus). Nous constatons donc que le choix de moduler fm=1200 Hz un tat des donnes et 2fm=2400 Hz lautre tat rpond un souci defficacit du dcodage : la convolution du signal acquis avec sin(2 fm t) donne une valeur moyenne nulle si le segment de signal ne code pas le bon tat et donne 1/2 si ltat recherch est prsent. Ainsi, il suffit dinitialement se synchroniser sur le flux de donnes - rle des 16 premiers octets qui oscillent 2400 Hz, puis effectuer deux produits des squences suivantes avec sin(2 fm t) et sin( fm t) pour retrouver ltat des bits successifs (Fig. 11). Finalement, ayant obtenu un flux de bits, il reste en interprter le contenu : ACARS exploite un codage dans lequel les transitions dun bit au suivant sont notifies, au lieu de coder directement ltat des bits eux-mmes. Ainsi, un signal 1200 Hz indique un changement dtat par rapport au bit prcdent, alors que 2400 Hz code le maintien de ltat prcdent17. Un exemple de mise en uvre par prototypage sous GNU/ Octave propose limplmentation suivante :
function binaire=fft_decod(filename,deb,fin,seuil) jmfdebug=0; fe=48000; f=fopen(filename); d=fread(f,inf,uint8); d=d(deb:fin); N=fin-deb;
puissance (u.a.)

20000

1200 Hz 2400 Hz

20000

1200 Hz 2400 Hz

15000
puissance (u.a.)

18000 16000 14000 12000 10000 8000 6000 160 180 200 220 numero dechantillon (48 kS/s) 240

10000

5000

500 1000 1500 2000 numero dechantillon (48 kS/s)

2500

Figure 11 : Signaux issu dun signal audio enregistr lors dune transmission ACARS sur 131,725 MHz avec application des algorithmes de filtrage 1200 et 2400 Hz tel que dcrit dans le texte. Insr droite, un zoom sur les premiers signaux exploitables en fin de synchronisation du rcepteur sur lmetteur (squence de plusieurs priodes 2400 Hz) : lidentification de ce point de dpart est un lment cl du bon dcodage de la suite de la trame car dfinit le premier bit du premier octet sur lequel tout le reste du dcodage se base.

Nous lisons le segment de donnes compris entre les indices deb et fin dans le fichier filename,
c=ones(60,1)/60; dm=conv(d,c);dm=dm(60/2:end-60/2); d=d-dm; % retranche moyenne glissante sur 3 periodes

application dune moyenne glissante (fentre rectangulaire de 60 points de longueur, soit 1,25 ms fe de 48 kHz),
t=[0:519]; % 2400 Hz dans 48 kHz = 20 points/periode *26 c2400x13=exp(i*t*2400/fe*2*pi); % recherche du max des 13 periodes a 2400 Hz s=conv(c2400x13,d); s=s(length(t)/2:end-length(t)/2); [a,b]=max(real(s)); % max de ressemblance pour decallage de b % plot(d(b-260:b+260)/120,g);hold on; plot(real(c2400x13),r);

17

leonardodaga.insyde.it/Corsi/AD/Documenti/ARINCTutorial.pdf

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

19

LAbO

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

le point cl de lalgorithme est de synchroniser le rcepteur sur les oscillations de lmetteur, et pour ce faire nous devons trouver le maximum de lintercorrlation entre la squence des signaux 2400 Hz mis par ACARS dans ce but de synchronisation. Nous gnrons donc un vecteur c2400x13 qui contient les valeurs dune sinusode chantillonne fe et de frquence 2400 Hz, et recherchons le maximum dintercorrlation qui, pour un signal rel, revient une convolution.
b=mod(b,20)+5; % revient au debut par pas de 2pi d=d(b+400:end); % bien se caler est fondamental pour la suite % est-il judicieux dessayer a +/-1 ?

if (jmfdebug==1) plot(rs12,bo-);end if (jmfdebug==1) hold on;plot(rs24,ro-);legend(1200,2400);end seuil=max(rs24)*0.55; l0=find((rs24+rs12)>seuil); % on ne garde que les points utiles rs12=rs12(l0);rs24=rs24(l0); ll=find(rs24>seuil);ll=ll(1) rs12=rs12(ll:end); rs24=rs24(ll:end);

Ayant identifi le point de mesure permettant de synchroniser les sinusodes synthtises de faon logicielle et les donnes acquises, nous avons choisi de replacer le curseur au dbut de la squence de mesure en nous dplaant par pas de 20 chantillons, soit une priode (48000/2400) de sinusode 2400 Hz. Cette tape est peut-tre inutile, mais vite de risquer de saccrocher sur une squence longue de signaux 2400 Hz se trouvant au milieu du message ACARS transmis :
t=[0:19]; % 2400 Hz dans 48 kHz = 20 points/periode c2400=exp(i*t*2400/fe*2*pi); c1200=exp(i*t*1200/fe*2*pi); s12=conv(c1200,d); s24=conv(c2400,d); % plot(d); hold on;plot(real(s12),r); plot(real(s24),r);

Finalement, la squence dchantillons est traite pour la convertir en valeurs binaires : nous recherchons, par critre de seuil, les valeurs pertinentes (signal au-dessus du bruit, ci-dessus) et les valeurs des bits par comparaison des sorties des deux filtres (convolutions, ci-dessous).
l=find(rs12>rs24);l=l(1) rs12=rs12(l:end); rs24=rs24(l:end); pos12=find(rs12>rs24); pos24=find(rs24>rs12); toutd(pos12)=0; toutd(pos24)=1;

Les valeurs binaires sont finalement rorganises en octets, selon la mthode vue auparavant sur le radiomodem, avec la valeur du bit codant la transition dtat ou le maintien de la valeur par rapport la valeur courante du bit.
n=1; tout(n)=1;n=n+1; % les deux premiers 1 sont oublies car on se sync sur 1200 tout(n)=1;n=n+1; for k=1:length(toutd) if (toutd(k)==0) tout(n)=1-tout(n-1); else tout(n)=tout(n-1);endif n=n+1; end binaire=reshape(tout(1:floor(length(tout)/8)*8),8,floor(length(tout)/8)); code_asc=binaire(:,1)+binaire(:,2)*2+binaire(:,3)*4+binaire(:,4)*8+binaire(:, 5)*16+binaire(:,6)*32+binaire(:,7)*64; checksomme=1-mod(sum(binaire(:,1:7)),2); % verification printf(%02x ,code_asc); printf(\n); printf(%c, code_asc); printf(\nCRC:); printf(%d,checksommebinaire(:,8)); printf(\n);

Nous recherchons dsormais les bits individuels, cods soit par une priode de 2400 Hz, soit une demi priode de 1200 Hz, soit dans tous les cas 20 chantillons,
t=[0:19]; % 2400 Hz dans 48 kHz = 20 points/periode fin20=floor(length(s12)/20)*20; s12=s12(1:fin20);s24=s24(1:fin20); rs12=reshape(abs(s12),20,length(s12)/20); rs24=reshape(abs(s24),20,length(s24)/20); rs12=sum(rs12); rs24=sum(rs24);

Les valeurs sont affiches sous forme hexadcimale, code ASCII correspondant, et validation du bit de parit. En rsum, ce code exploite la trame ACARS de la faon suivante : 1.  Identification de loccurrence du dbut de trame sous forme de plusieurs oscillations 2400 Hz : nous nous sommes imposs de trouver au moins 13 priodes du signal 2400 Hz pour dfinir le dbut de trame et synchroniser notre traitement sur la phase du signal acquis. 2.  Identification des segments de 1 (2400 Hz) et de 0 (1200 Hz) par convolution dune priode de sinusode de chacune des frquences avec le signal traiter. Seule une unique convolution est utile car lincertitude sur la phase (qui ncessiterait par exemple 20 convolutions pour le signal 2400 Hz pour identifier la phase parmi

contrairement au cas prcdent du XE1203F o nous nous tions contents de prendre un point sur 40 pour tenir compte de la frquence de bits transmis, cette fois nous allons moyenner les valeurs des chantillons au sein de chaque bit pour amliorer le rapport signal bruit (et donc la capacit de dcodage du message en milieu bruit). Pour ce faire, nous rorganisons les deux vecteurs de mesures filtres par les squences de sinusodes 1200 et 2400 Hz sous forme dune matrice de 20 points de large (la longueur en chantillons dun bit), et allons sommer les lments pour effectuer la moyenne. rs12 et rs24 contiennent les informations permettant didentifier si un bit est plus problement 1 ou 0 et mrite dtre affiches dans une phase prliminaire de dverminage (Fig. 11).

20

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

les 20 valeurs possibles qui maximisent lintercorrlation) a dj t rsolue lors de ltape prcdente.

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

3.  Le codage des informations reprsentant une transition dun tat un autre et non ltat lui-mme, il reste convertir la squence de bits issue de la convolution en des valeurs interprtables en ASCII. Noter en particulier que la documentation http://www.pervisell.com/ ham/raftmode.htm#I76 est errone concernant la parit du flux de donnes. Il est par ailleurs remarquable denfin comprendre la signification dentres tranges de la table ASCII (man ascii), telles que le caractre 01 (dbut den-tte), 02 (dbut de texte) ou 03 (fin du texte) qui sont exploites par ACARS. Par ailleurs, le fait de coder la transition induit que ds la premire erreur de dcodage, tout le reste du message sera illisible. Ainsi, nous aurons souvent lidentifiant de lavion mettant le message, mais obtenir tout le contenu du message lui-mme est difficile car dpendant de labsence derreur de traitement des bits tout au long du message. Lapplication dune convolution entre deux sries de donnes de longueur respective M et N pose toujours un problme de dfinition de lorigine. En effet, la version numrique (discrte) de la convolution c entre ui, i[1..M] et v j, j[1..N], est

Dans lquation ci-dessus, lintgrale dont les bornes sont peut en pratique tre longue calculer, linfini tant difficile atteindre. On intgrera donc, pour deux sries de points de longueurs M et N, soit entre max(M,N) si nous faisons glisser la srie des u sur les v pour gnrer ainsi un total de max(M,N) points, ou alternativement une srie de M+N points si nous compltons une des deux sries par des 0 pour galer la longueur des deux sries. Cette approche est par exemple celle propose dans le code traduit en C que nous dvelopperons ci-dessous (section 5.2), puisque le passage par Fourier impose de multiplier point par point deux squences de longueurs gales. Le problme de la position de lorigine se pose donc selon le formalisme slectionn, et la principale difficult rencontre dans la conversion du code GNU/Octave vers C se trouve ce niveau (sans compter les conventions de normalisation de la transforme de Fourier qui imposent de recalculer les seuils dans la nouvelle implmentation). Le programme GNU/Octave ci-dessus identifie le dbut de trame (srie doscillations 2400 Hz), affiche la squence des valeurs hexadcimales dcodes, leur interprtation dans le code ASCII, et lapplication du bit de parit la squence ainsi dcode. Dans le rsultat ci-dessous, nous constatons que toutes les valeurs ont t convenablement dcodes, sauf les 9 dernires, probablement sans importance car situes aprs le caractre ASCII 0x03 (fin de la chane de texte). Nous affichons ci-dessous dans un premier temps les valeurs hexadcimales des octets dcods (commenant toujours par la squence de synchronisation 0x2b 0x2a 0x16 0x16 si le dcodage est effectu correctement), linterprtation selon le code ASCII si le caractre est affichable, et finalement ladquation avec le bit de parit (0 pour la cohrence avec ce bit, 1 sil y a erreur) :
binaire=fft_decod(acars_orleans.wav,101001+2.15e6,101001+2.15e6+40000,7000); 2b 2a 16 16 01 58 2e 47 2d 45 55 55 47 15 48 31 39 02 43 30 33 41 42 41 39 32 31 36 23 43 46 42 57 52 4e 2f 57 4e 31 32 30 36 33 30 30 38 33 33 30 30 33 34 30 30 30 30 30 36 4e 41 56 20 49 4c 53 20 32 20 46 41 55 4c 54 20 20 20 20 20 20 20 20 20 0d 03 6d 1d 7f 7f 7f 7f 7f 7f 7f m*X.G-EUUGH19C03ABA9216#CFBWRN/WN12063008330034000006NAV ILS 2 FAULT CRC:000000000000000000000000000000000000000000000000000000000000000000000000000000000000-100-1-1-1-1-1-1

Il est toujours intressant de savoir quun avion - ici G-EUUG qui est un Airbus A320 de British Airways18 allant de Londres lItalie au cours du vol BA9216 - est en train de voler avec un dfaut sur son instrumentation secondaire datterissage19. Les abrviations des messages sont dcrites http://www.angelfire.com/sc/ scannerpost/acars.html.

5 Du prototypage lexploitation sous gnuradio


Gnuradio-companion convertit un schma de traitement dfini de faon graphique en script Python, faisant appel aux fonctions correspondantes. Cependant, les donnes qui transitent entre les blocs, i.e. le flux issu des dmodulateurs I/Q, ne passent que dun bloc lautre sans tre accessibles depuis le script Python (code 1, correspondant au schma graphique de la Figure 8). Chacun de ces blocs est lui-mme cod en Python ou C(++), suivant un protocole dchange de donnes20. Nous allons donc traduire le code C dexemple de dcodage des trames FSK pour respecter les conventions de blocs gnuradio-companion et ainsi effectuer le traitement en temps rel (au lieu denregistrer les informations dans un fichier binaire en vue de son post-traitement).

avec u et v gaux 0 en dehors des intervalles cits ci-dessus. Dans le cas du passage dans le domaine de Fourier, les squences u ou v sont compltes de 0 (zero padding ) pour avoir la mme taille (et sapprocher de la puissance de 2 suprieure la plus proche dans le cas de la transforme de Fourier rapide).

18 19 20

www.planespotters.net http://www.scancat.com/Code-30_html_Source/acars.html pour le contenu des trames et en particulier de len-tte. http://gnuradio.org/redmine/projects/gnuradio/wiki/BlocksCodingGuide

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

21

LAbO

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

self.wxgui_scopesink2_0 = scopesink2.scope_sink_f( self.GetWin(), title="Scope Plot", [...] ) self.Add(self.wxgui_scopesink2_0.win) self.gr_throttle_0 = gr.throttle(gr.sizeof_float*1, samp_rate) self.gr_file_source_0 = gr.file_source(gr.sizeof_char*1, "nom_du_ fichier.wav", True) self.gr_char_to_float_0 = gr.char_to_float(1, 1) self.connect((self.gr_throttle_0, 0), (self.wxgui_scopesink2_0, 0)) self.connect((self.gr_char_to_float_0, 0), (self.gr_throttle_0, 0)) self.connect((self.gr_file_source_0, 0), (self.gr_char_to_float_0, 0)) tb = top_block() tb.Run(True) Tableau 1 : Le code Python gnr par gnuradio-companion ne donne pas accs au flux de donnes radiofrquences mais ne fait que dfinir des blocs et les connecter entre eux pour router les informations dune unit de traitement la suivante.

Enter valid argument list, including default arguments: Add Python QA code? [Y/n] Add C++ QA code? [Y/n]

La premire ligne permet de directement spcifier les paramtres que le bloc recevra au moment de son instanciation (type de donne, gain, seuil, ...). Les deux lignes suivantes correspondent lajout (ou pas) de test-unitaire pour le bloc. lissue de cette tape, les rpertoires ont t peupls avec les fichiers ncessaires et ceux-ci partiellement remplis. Trois fichiers retiendront principalement notre attention :
grc/nomDuProjet_nomDuBloc.xml : ce fichier fournit - la description du bloc gnuradio-companion. Il stipule, entre autres, le nom du bloc (balise name), dans quelle catgorie il doit tre rang (balise category), les paramtres (balise param) ainsi que leurs noms, type et variables correspondantes, et les entres (sink) et les sorties (source). Un exemple dun tel fichier qui passe un paramtre (valeur relle seuil) la mthode de traitement des donnes decodeur de la classe acars est :
<?xml version="1.0"?> <block> <name>decodeur</name> <key>acars_decodeur</key> <category>acars</category> <import>import acars</import> <make>acars.decodeur($seuil)</make> <param> <name>Threshold</name> <key>seuil</key> <type>real</type> </param> <sink> <name>in</name> <type>float</type> </sink> </block>

Le dveloppement de blocs pour la gnuradio ncessite lutilisation dun environnement particulier constitu dun rpertoire contenant lui-mme des sous-rpertoires dans lesquels seront stocks les diffrents fichiers ncessaires lexploitation du bloc. La premire tape pour la cration dun (ou plusieurs) bloc(s) est donc de disposer de cet environnement de dveloppement. Toutefois, afin dviter ltape fastidieuse de la cration manuelle de larborescence, nous allons utiliser le script gr-modtool.py21. Cet outil sert la fois gnrer le squelette du rpertoire et de ses sous-rpertoires, mais galement de le peupler. La cration du projet se fait avec la commande suivante :
gr_modtool.py create plop

l issue de cette commande, un rper toire g r nomduprojet apparat dans le rpertoire courant et comporte (entre autres) les rpertoires : -g  rc pour les fichiers de descriptions utiliss par gr-companion ; - include pour les en-ttes ; - lib pour les fichiers sources C++ dextension .cc. Lajout dun bloc de traitement du signal numrique dans le projet se fait avec la commande (il faut se trouver dans le rpertoire du projet) :
gr_modtool.py add -t general plup

-i  nclude/nomDuProjet_nomDuBloc.h et lib/nomDuProjet_nomDuBloc.cc : la classe et son implmentation. Par dfaut, ils contiennent : - un constructeur priv, - un destructeur public, -u  ne fonction nomDuProjet_make_nomDuBloc dfinie comme friend vis--vis de la classe (donc pouvant accder au constructeur) et dont le rle est de retourner une instance de la classe, - une mthode publique general_work. Ces concepts abstraits de larborescence seront illustrs par des bouts de code plus loin dans ce document (section 5.3), et le lecteur est encourag consulter le code dexemple disponible http://jmfriedt.free.fr/gr-acars.tar.gz ou sur le site de CGRAN www.cgran.org/wiki/ACARS.

Largument -t spcifie le type de bloc, dans le cas prsent nous demandons un type gnrique mais il existe dautres types tels que des sinks, des sources, des dcimateurs, ... Comme nous le verrons un peu plus bas, le type va impacter sur la signature de certaines mthodes
21

git://github.com/mbant/gr-modtool.git

22

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

La dernire mthode peut galement sappeler work selon le type du bloc. Cette mthode est sans doute la plus importante car cest elle qui reoit le flux venant du bloc prcdent dans la chane, ralise le traitement et fournit les nouvelles donnes. Sa signature est la suivante :
int plop_plup::general_work (int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)

avec noutput_items qui comme son nom ne lindique pas, donne le nombre dinformations reues, input_items un tableau contenant les donnes entrantes et qui doit tre recast dans le bon type, output_items le tableau que le bloc doit remplir avec les donnes traites. ninput_items peut ne pas exister, selon le type du bloc, et semble ne pas servir grand chose. Afin de compiler notre application, nous oprons comme avec toute archive rencontre jusquici pour gnuradio : cration dun sous-rpertoire build dans larborescence des sources du module compiler, excuter cmake ../ aprs tre rentr dans ce rpertoire, puis make VERBOSE=1 && make install. Noter quune fois le bloc nouvellement cr dans gnuradio-companion (dans la liste des menus de la colonne de droite), il est inutile de relancer linterface graphique suite chaque recompilation. En effet, le code Python qui est excut en pratique est rgnr chaque fois que nous cliquons sur licne avec des engrenages, et le module nouvellement compil recharg. Nous aurons donc toujours la dernire version du module compil et install par make install disponible lors de lexcution de la chane de traitement (Fig.12).

Figure 12 : Dcodage du flux dinformations issu dun radiomodem XE1203F par traitement logiciel des donnes I et Q pour en extraire linformation numrique mise, dans un premier temps enregistr dans un fichier binaire (.wav) et restitu pour valider le bon fonctionnement du bloc (nomm square). Noter, en bas du menu droite, lajout dune entre HOWTO avec le module square, qui correspond au rsultat de la compilation de notre module de traitement. Il est inutile de relancer gnuradiocompanion lors de modifications des fonctions de square : le bloc est recharg lors de la gnration du code Python chaque nouvelle excution de la squence de traitements.

5.1 Cas du radiomodem XE1203F


Ayant prototyp les mthodes de filtrage sous GNU/Octave, nous dsirons pouvoir afficher les donnes dcodes en temps rel. Les tapes de ce portage se font en 3 tapes : 1.  Conversion dun script GNU/Octave en C et vrification de toutes ses fonctionnalits en lisant un enregistrement dun fichier audio (ou binaire si sa frquence dchantillonnage nest pas compatible avec celle de la carte son) et application des filtres implments en C. Cette tape a encore lavantage de pouvoir traiter lintgralit des donnes contenues dans le fichier (code 2). 2.  Conversion du programme cit ci-dessus pour travailler sur des segments de donnes de taille alatoire (Fig. 14), reprsentatives des bouts de donnes qui seront fournis par les blocs de dmodulation et de filtrage de gnuradio. 3.  Intgration du code C(++) ainsi gnr dans le formalisme dun bloc gnuradio.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

23

LAbO

#define MAXSIZE 100000 #define NSEARCH 260 // 13 periods * 20 pts/period void {int for for } conv1(unsigned char* in,int* out,int N,int len) somme=0,k; (k=0;k<len;k++) somme+=(int)in[k]; // moyenne glissante sur len points (k=len;k<N;k++) {somme=somme-in[k-len]+in[k];out[k-len]=somme/len;}

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

#define segment 8192 int main(int argc,char **argv) {char filename[255]; int deb,seuil,courant; int k,i,fe=192000,f,N; int dm[MAXSIZE]; unsigned char d[MAXSIZE],code_asc; int b=0,l0=0,pos=0; if (argc<4) printf("%s filename deb seuil\n",argv[0]); else {sprintf(filename,"%s",argv[1]);deb=atoi(argv[2]);seuil=atoi(argv[3]);} deb=0; do { f=open(filename,O_RDONLY); // lecture de segment donnees dans le fichier de points k=segment; i=lseek(f,deb,SEEK_SET); if (i!=deb) fprintf(stderr,"lseek error %d\n",k); N=read(f,&d[pos],k); printf("\nN=%d\n",N); close (f); conv1(d,dm,N,20); // c=ones(20,1)/20;dm=conv(d,c);dm=dm(20/2:end-20/2); for (k=0;k<N;k++) if (dm[k]<seuil) dm[k]=1; else dm[k]=0; // k=find(dm<100);dm(k)=0; k=find(dm>=100);dm(k)=1;dm=1-dm; // % etat au repos est 1, start bit est passage a 0 courant=0; while (courant<(N+pos-380)) { // k=find(dm(courant:end)<1);dm=dm(k(1)+courant-1:end); do {courant++;} while ((dm[courant]==1)&&(courant<(N+pos-380))); if (courant<(N+pos-380)) // db=dm(20:40:20+40*9); % 10 bits = START+9, 40 points/bit {code_asc=dm[courant+60]+dm[courant+100]*2+dm[courant+140]*4+dm[courant+180]*8+ dm[courant+220]*16+dm[courant+260]*32+dm[courant+300]*64+dm[courant+340]*128; if (code_asc>0) { if (dm[courant+380]==0) {} // printf("err "); // stop bit error else {if (((code_asc>=32)&&(code_asc<128))||(code_asc==\n)||(code_asc==\r)) printf("%c",code_asc); else printf("\\%x",code_asc); } } courant+=380; // milieu du stop bit de loctet qui vient detre traite } } memcpy(d,&d[courant],N+pos-courant); // copie ce qui reste de donnees pos=N+pos-courant; deb+=segment; } while (N==segment); // boucle sur deb pour simuler blocs grc printf("\n");

Tableau 2 : Traduction en C du code prototyp sous GNU/Octave pour le dcodage des transmissions dun radiomodem XE1203F modul en frquence (FSK) pour une transmission numrique de donnes 4800 bits/s. Nous avons laiss en commentaires les principales squences du code pour GNU/ Octave que nous avons traduites. Noter la lecture du fichier par segments de segment lments, et concatnation des valeurs qui nont pu tre traites car ne formant pas un bit dinformation complet, reprsentatif du flux de donnes que nous fournira gnuradio lors dun dcodage en temps rel.

Le problme de la gestion de la taille des donnes traiter est rsolu de la faon suivante : nous savons quun octet complet tient sur 10 bits (start, 8 bits de donnes, stop) donc 400 chantillons pour un signal chantillonn 192000 Hz et transmis 4800 bits/s (192000/480010=400). Nous allons donc tout dabord rechercher loccurrence dun start bit (passage de 1 - tat au repos - 0 - tat du start bit22), et si la masse de donnes traiter dpasse 400 bits, nous continuons le traitement consistant tester la valeur du bit tous les 40 chantillons (puisque 192000/4800=40). Comme dans toute communication asynchrone, le start bit permet de se resynchroniser pour les 9 bits qui vont suivre : nous vrifions que le stop bit est bien 1, et recherchons chantillon par chantillon loccurrence du prochain passage 0 pour

UUUU\bc\e7\fb\822 .0 \fc000 465 31 534 6002109 \c\f8\e0UUU\bc\e7\93\82\fe .0 00\fc0 558 31 500 7 02110 \fc\c0UUU\bc\e7\93\822 0 0000595 31 16\f9 8 02110 U\e0UUUU\bc\93\822 .0\fc0000 6\ff7 31 426 9 02110 \ff\b0E\e0UUUU\bc\e7\93\fe2 .0 0T00 225 31374 10 0210 \fc\f0UUUU\bc\e7\93\82\fe .0 000 333 31 24 12 02110 \ff\ff\e0\c1UUU\bc\e7\93\822 .0 0\bc00 203\bc31 419 13 02111 \ff\5\ff\f8\c0U5UU\bc\e7\93\822 .0 00\e40 367 \e71 246 14 02111 \f8\f0\e0UUU\bc\e7\93\822 .0 000\94 195 3\95 296 15 02111 \f8\f0UUUU\bc\e7\93\822 \fe0 0000\fc284 31 30\fd 17 02111 \ff\e0\5\f0\f0\e0UUUU\bc\e7\93\822 .0 0000\d02\f09 31 311 \859 02112 \ff\e0\f0\f0\e8\e0UUUU\bc\e7\93\822 .0 0000 336 31 \e741 20 021\e52

2 .0 2 .0 2 .0 2 .0 2 .0 2 .0 2 .0 2 .0 2 .0 2 .0 -> 2 2 .0 2 .0

0000 465 31 0000 558 31 0000 595 31 0000 637 31 0000 225 31 0000 333 31 0000 203 31 0000 367 31 0000 195 31 0000 284 31 .0 0000 201 0000 209 31 0000 336 31

534 6 02109 500 7 02110 169 8 02110 426 9 02110 374 10 02110 324 12 02110 419 13 02111 246 14 02111 296 15 02111 305 17 02111 31 325 18 02112 311 19 02112 341 20 02112

Tableau 3 : Comparaison des trames issues du dcodage par gnuradio des signaux reus par rcepteur EZCAP (gauche), et les trames mises par le radiomodem. Les trames de gauche commencent par le signal de synchronisation UUUU, suivi dun identifiant du modem metteur, suivi de la trame. Bien que la conversion ne soit pas parfaite, la majorit des trames mises (droite) se retrouve dans les signaux dcods (gauche). Nous avons indiqu dans la table de droite une ligne prfixe par une flche qui a compltement t omise lors du dcodage par chec du dcodage de la trame UUUU dinitialisation de la transmission.

22

http://en.wikipedia.org/wiki/Asynchronous_serial_communication

24

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

N=1361 N=5444 N=6805 \fcUUUU\bc\e7\93\2 N=1361 2 . N=682 0 N=1361 000 N=1361 0 4\fe N=1361 6 3 N=1361 1 4\fd N=4083 0 31 01138 N=5444 *7C12 188 N=5444 N=1361 N=1361 N=1361 N=2722 N=1361 N=1361 N=5444 N=6805 \f0 \f0

\10\fc UUUU\bc\e7\93\822

Figure 14 : Le bloc compatible gnuradio quip, pour le dverminage, de laffichage dune variable N contenant le nombre de donnes fournies par le bloc de dmodulation : nous constatons que cette valeur volue de faon plus ou moins alatoire, et quil est donc impossible de faire une hypothse sur la taille des donnes traiter. La solution propose est dcrite dans le texte.

Figure 13 : Haut : schma bloc de gnuradio-companion pour le dcodage des trames acquises par EZCAP et fournies aprs dmodulation au bloc de traitement que nous avons dvelopp et test sur carte son. Noter le gain important (environ 3700) et le biais (128) quil faut ajouter pour ajuster la gamme des donnes issues du bloc de dmodulation aux valeurs lues dans le fichier .wav exploit pour les traitements. Bas : montage exprimental, avec le radiomodem XE1203F command par un microcontrleur STM32, et le module EZCAP pour lcoute du flux de donnes mis.

relancer un dcodage. Si la quantit de donnes restant traiter aprs dtection dun start bit est infrieure 400, alors nous copions en dbut de tableau les donnes restantes, et concatnons les nouvelles donnes pour relancer le traitement sur un jeu de donnes complet. Si aucune transmission nest dtecte sur les donnes acquises, la recherche de la transition du start bit atteint la fin du tableau et nous pouvons sereinement traiter le nouveau paquet de donnes sans craindre davoir coup une transmission en cours. Le rsultat de cette implmentation (Fig. 13) est visible sur la table 3.

5.2 Cas de lACARS - attention, paragraphe addictif


La philosophie que nous avons adopte ici pour convertir le code de traitement prototyp sous GNU/Octave vers un flux de donnes de taille alatoire consiste concatner les donnes reues pour former un bloc contenant lintgralit des donnes, et de nappliquer la phase de dcodage que sur lintgralit

de ce bloc, pour revenir aux conditions dj connues sous GNU/Octave. Lintrt dun bloc est dtermin par la convolution entre le signal acquis et un filtre centr sur 2400 Hz. Nous avons dj vu que toute communication ACARS sinitie avec plusieurs priodes dun signal 2400 Hz pour laisser le temps au contrle de gain automatique du rcepteur radiofrquence de se stabiliser et synchroniser lhorloge du rcepteur avec celle de lavion. Ce signal sert donc identifier le dbut dun message. Ensuite, nous concatnons les donnes pour atteindre la taille maximale que pourrait atteindre un message ACARS (nous avions tent de concatner tant que la puissance du signal reu dpasse un seuil prdtermin, mais cette approche savre trs sensible la valeur du seuil de dtection), soit 258 caractres compte tenu de la taille de texte la plus longue admissible. La traduction du code GNU/Octave en C se fait alors sans trop de problme si ce nest pour la convolution qui nest

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

25

LAbO

efficacement implmente que par le passage dans le domaine de Fourier. Heureusement, une bibliothque vient notre secours pour viter de rimplmenter ces fonctions : libfftw3.

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

k=lseek(f,deb,SEEK_SET); if (k!=deb) fprintf(stderr,"lseek error %d\n",k); N=read(f,d,fin-deb); close (f); // d=d(deb:fin); N=fin-deb; out=(int*)malloc(sizeof(int)*N); remove_avg(d,out,N,60); // c=ones(60,1)/60; dm=conv(d,c);dm=dm(60/2:end-60/2); d=d-dm;

Remarque
gnuradio exploite un environnement de compilation visant tre portable entre un*x, MacOS X, et MS-Windows, cmake, ou le Cross Platform Make (www.cmake. org). Alors quajouter une bibliothque dans un classique Makefile se rsumait ajouter le nom de la bibliothque prcd de -l, cmake a pour ambition de trouver tout seul les bonnes bibliothques aux bons emplacements, et ce quel que soit lenvironnement de dveloppement. Pour ajouter libfftw3, nous avons d piocher dans le script de recherche de larborescence disponible http://code.google.com/p/qmcpack/source/ browse/trunk/CMake/FindFFTW.cmake, et complter le CMakeLists.txt (pendant du classique Makefile de notre enfance) par find_package(FFTW) et INCLUDE_ DIRECTORIES($FFTW_INCLUDE_DIR) pour la recherche den-tte et LINK_LIBRARIES($FFTW_LIBRARIES) pour la portabilit des bibliothques.
#include <fftw3.h> #define MAXSIZE 1000000 #define NSEARCH 260 // 13 periods * 20 pts/period void remove_avg(unsigned char *d,int *out,int tot_len,int fil_len) {int tmp,k,avg=0; for (k=0;k<fil_len;k++) avg+=d[k]; // initialise moyenne glissante for (k=0;k<tot_len-fil_len;k++) {out[k]=d[k]-avg/fil_len; avg-=d[k]; avg+=d[k+fil_len]; } for (k=tot_len-fil_len;k<tot_len;k++) out[k]=d[k]-avg/fil_len; }

La lecture du fichier de points acquis par gnuradio-companion est triviale - un octet par donne qui ne pose donc pas de problme dendianness - et lindice de dbut de la squence analyse dans le fichier va nous servir par la suite simuler le fait que le flux de donnes issu des dmodulateurs de gnuradio peut avoir des tailles variables.
c2400x13 = (fftw_complex *) fftw_malloc (sizeof (fftw_complex) * N); [... idem pour initialiser fc2400x13, fd, s, ss ...] for (t=0;t<520;t++) // t=[0:520]; c2400x13=exp(i*t*2400/fe*2*pi); {c2400x13[t][0]=cos((double)t*2400./fe*2*M_PI); c2400x13[t][1]=sin((double)t*2400./fe*2*M_PI); } for (t=520;t<N;t++) {c2400x13[t][0]=0;c2400x13[t][1]=0;} // 13 periodes 2400 Hz for (k=0;k<N;k++) {s[k][0]=(double)out[k];s[k][1]=0.;} plan_a=fftw_plan_dft_1d(N, c2400x13, fc2400x13, FFTW_FORWARD, FFTW_ESTIMATE); plan_b=fftw_plan_dft_1d(N, s, fd , FFTW_FORWARD, FFTW_ESTIMATE); plan_R=fftw_plan_dft_1d(N, fd,ss, FFTW_BACKWARD, FFTW_ESTIMATE); fftw_execute (plan_a); fftw_execute (plan_b); for (k=0;k<N;k++) // produit des transformees de Fourier pour intercorrelation {mul[0]=fc2400x13[k][0]*fd[k][0]-fc2400x13[k][1]*fd[k][1]; mul[1]=fc2400x13[k][1]*fd[k][0]+fc2400x13[k][0]*fd[k][1]; fd[k][0]=mul[0]/(float)N; fd[k][1]=mul[1]/(float)N; } fftw_execute (plan_R); // puis retour dans le domaine reel par FFT inverse fftw_destroy_plan (plan_a); fftw_destroy_plan (plan_b); fftw_destroy_plan (plan_R); // s=conv(c2400x13,d);

Cette premire fonction de retrait de la valeur moyenne rappelons que lintercorrlation qui sera utilise pour trouver la squence de sinusodes 2400 Hz suppose un signal de valeur moyenne nulle - retire le rsultat dune fentre glissante de fil_len lments du tableau d pour gnrer out. Ce pr-traitement est fondamental pour toute la suite des oprations.
int main(int argc,char **argv) {char filename[255]; int deb,fin,seuil,k,i,fe=48000,f,N,t,*out,n,b=0,l0=0; unsigned char d[MAXSIZE],*toutd,*tout; double a=0.,*rs12,*rs24,*rc12,*rc24,c2400[20], c1200[20],s2400[20], s1200[20]; fftw_complex *c2400x13,*fc2400x13,*fd,*s,mul,*ss; fftw_plan plan_a, plan_b, plan_R; if (argc<5) printf("%s filename deb fin seuil\n",argv[0]); else {sprintf(filename,"%s",argv[1]); deb=atoi(argv[2]); fin=atoi(argv[3]); seuil=atoi(argv[4]); } if ((fin-deb)>MAXSIZE) {fin=deb+MAXSIZE; fprintf(stderr,"deb=%d fin=%d\n", deb,fin); } f=open(filename,O_RDONLY); if (f<0) fprintf(stderr,"open error %d\n",f);

Lappel aux fonctions de transforme de Fourier proposes par fftw3, opration fastidieuse implmenter par ailleurs, passe par lallocation de mmoire des divers tableaux exploits par les tapes intermdiaires de calcul de lintercorrlation en passant dans le domaine de Fourier (pour rappel, nous avions dj explicit dans ces pages [13] le gain en temps de calcul - de N2 Nln(N) - lors de la recherche dun motif dans une squence de points de taille N par intercorrlation). Les motifs recherchs sont dfinis sous forme de segments de sinusodes normaliss par la frquence dchantillonnage fe=48000 Hz.
for (k=0;k<N-NSEARCH;k++) if (ss[k+NSEARCH-2][0]>a) {a=ss[k+NSEARCH-2][0];b=k;} // [a,b]=max(real(s)); printf("a=%f b=%d\n",a,b); b=b%20;

Le maximum dintercorrlation identifie lindice, dans le temps, pour lequel le motif des sinusodes 2400 Hz a t identifi dans la squence de points exprimentaux. Cette identification est un point cl pour optimiser la suite des oprations car rsout lincertitude sur la phase. En effet, nous avons vu dans la prsentation des squences I et Q issues des mlangeurs que deux paramtres inconnus sont

26

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

lamplitude et la phase du signal. Lintercorrlation permet didentifier les deux paramtres, mais au prix dun calcul lourd. Si la phase est connue, alors il ne reste que lamplitude identifier, et ceci ne ncessite que N multiplications en faisant glisser le motif dune priode de sinusode sur les points exprimentaux par pas dune priode (et non plus par pas dun point dchantillonnage). Cest ce que nous allons faire ci-dessous avec une priode de sinusode 2400 Hz et une demi-priode 1200 Hz, chacune encodant un tat du flux de donnes numriques. Nous prendrons ensuite le module du produit de convolution pour viter le cas de lopposition de phase qui donnerait un rsultat de magnitude leve mais ngatif.
for (t=0;t<20;t++) // t=[0:520]; c2400x13=exp(i*t*2400/fe*2*pi); {c2400[t]=cos((double)t*2400./fe*2*M_PI); // t=[0:20]; % 2400 Hz dans 48 kHz = 20 points/periode s2400[t]=sin((double)t*2400./fe*2*M_PI); // c2400=exp(i*t*2400/fe*2*pi); c1200[t]=cos((double)t*1200./fe*2*M_PI); // c1200=exp(i*t*1200/fe*2*pi); s1200[t]=sin((double)t*1200./fe*2*M_PI); } rs12=(double*)malloc(sizeof(double)*(N-b)/20); // fin20=floor(length (s12)/20)*20; [... idem pour rs24, rc12, rc24 ...] l0=0; for (k=b;k<N-20;k+=20) {rs12[l0]=0.; rs24[l0]=0.; rc12[l0]=0.; rc24[l0]=0.; for (t=0;t<20;t++) {rs24[l0]+=((double)out[k+t]*s2400[t]); rc24[l0]+=((double) out[k+t]*c2400[t]); rs12[l0]+=((double)out[k+t]*s1200[t]); rc12[l0]+=((double) out[k+t]*c1200[t]); } rs12[l0]=sqrt(rs12[l0]*rs12[l0]+rc12[l0]*rc12[l0]); rs24[l0]=sqrt(rs24[l0]* rs24[l0]+rc24[l0]*rc24[l0]); l0++; }

bits selon les valeurs de toutd et affichons dans un premier temps les valeurs hexadcimales des octets dcods - une trame ACARS devant commencer par 2B 2A 16 16 01 puis la squence des caractres affichables en les interprtant par leur code ASCII.
n=0; tout[n]=1;n++;tout[n]=1;n++; // les deux premiers 1 sont oublies car on se sync sur 1200 for (k=0;k<fin-l0;k++) {if (toutd[k]==0) tout[n]=1-tout[n-1]; else tout[n]=tout[n-1]; n=n+1; } for (k=0;k<fin-l0;k+=8) printf("%02x ",tout[k]+tout[k+1]*2+tout[k+2]*4+tout[k+3]*8+tout [k+4]*16+tout[k+5]*32+tout[k+6]*64); printf("\n"); for (k=0;k<fin-l0;k+=8) printf("%c", tout[k]+tout[k+1]*2+tout[k+2]*4+tout[k+3]*8+tout [k+4]*16+tout[k+5]*32+tout[k+6]*64); } // checksomme=1-mod(sum(binaire(:,1:7)),2); % verification

Nous avons omis le calcul du bit de parit qui ne nous aide de toute faon pas retrouver la valeur initiale de loctet corrompu lors de la transmission, les codes correcteurs permettant ce genre de manipulation tant bien plus complexes quun simple bit en fin de chaque octet. Ayant valid que le code en C fournit des rsultats cohrents avec le script GNU/Octave observ initialement, nous incluons ce programme dans lenvironnement C++ impos par gnuradio-companion tel que vu auparavant. La FFT ncessitant un nombre minimum de donnes traiter, nous avons fait le choix de, plutt que concatner juste le morceau final de donnes qui na pu tre dcod tel que nous lavions vu pour la radiomodem XE1203, accumuler autant de points que le nombre maximum de caractres que peut contenir un message ACARS, savoir 258 caractres. Le dcodage des 13 squences adjacentes doscillations 2400 Hz se fait en continu sur le flux de donnes acquis (avec ici la contrainte dun nombre minimum de 20 points/priode13 priodes=260 points), et lorsquune condition de seuil est atteinte (signifiant un dbut de trame), nous accumulons 40 points/bit8 bit/caractre258 caractres, soit environ 83000 points. Lalgorithme de dcodage que nous avons implment en C sapplique alors ces 83000 points comme sils avaient t lus dans un fichier (Fig. 15, page suivante). Nous avons cependant observ une trs grande sensibilit du dcodage aux valeurs de seuils slectionns, un point peu satisfaisant qui mrite tre amlior par lutilisation de contrles de gains automatiques. Le message dcod diffre lgrement de ce qui est obtenu avec le programme en C ci-dessus et contient :
+*2.HB-JZTH2-M10DDS39AZ0G N47307E0060672854M380240049G N47317E0 060012986M410240050G N47333E005JLGLOHLrTLMMLFOJN8____1KHLJ2EPOJKHIL.50145524@O%0G____1K038 1E00JKNGLML[2KHZ=C+05O8 N4H+AJ9OO53&4LC12MT&2""80:*8_ N$4DK7E@_Z31J@

Les donnes brutes sont passes dans le filtre quest la convolution, il ne reste plus maintenant qu comparer les amplitudes des signaux issus de chaque filtre pour estimer si le bit est plus probablement un 1 ou un 0 :
l0=0; // il faut liberer toutes les allocations de memoire (malloc) par free ... omis ici do l0++; while ((rs24[l0]+rs12[l0])<2*seuil); // cherche debut do l0++; while ((rs24[l0]+rs12[l0])>2*seuil); // cherche fin fin=l0; l0=0; do l0++; while (rs24[l0]<seuil); // ll=find(rs24>seuil);ll=ll(1); rs12=rs12(ll:end);rs24=rs24(ll:end); do l0++; while (rs12[l0]<rs24[l0]); // l =find(rs12>rs24); l=l(1); rs12=rs12(l:end); rs24=rs24(l:end); toutd=(char*)malloc(fin-l0); tout=(char*)malloc(fin-l0+2); for (k=l0;k<fin;k++) // pos12=find(rs12>rs24);pos24=find(rs24>rs12) ;toutd(pos12)=0;toutd(pos24)=1; if (rs24[k]>rs12[k]) toutd[k-l0]=1; else toutd[k-l0]=0;

et ayant un flux de donnes binaires contenu dans toutd, nous achevons le dcodage en inversant ltat courant des

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

27

LAbO

mis par un Airbus A319 (HB-JZT) de EasyJet suisse (cohrent pour une coute effectue Besanon) et semble contenir des transmission de coordonnes (47,307 N, 6.607 E correspond bien au Nord-Est de la Franche-Comt) dont nous ne connaissons pas la signification. La fin du message est probablement corrompue.

+*R.OO-SNBH19C00ASN07LR#CFBFLR/ FR12081915430036110006PRESS REG-V 4001HA1 OR SOL 10HA1 OR SENSE LINE/IDBMC 1!

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Nous ne savons pas ce que appuyer sur le bouton REG-V effectue (apparemment une histoire de valve de rgulation de la pression de la cabine), mais cela semble important pour que le pilote en informe le sol, et est un message rcurent que nous retrouvons dans diverses archives de messages ACARS sur le Web ! Ces rsultats ne semblent pas significativement plus mauvais que les dcodeurs exploitant lacquisition par carte son de la sortie dun scanner radiofrquence que nous avons test (le maintenant dfunt KRACARS23 notamment, pour DOS). Les perspectives damliorations du rcepteur de mode numrique ACARS tiennent probablement en une dtection automatique dun paramtre de seuil qui nous sert identifier le premier bit du premier octet, dont toute la suite du message dcoule. Ce seuil est actuellement dfini de faon statique, une faon peu apte sadapter aux vastes gammes de conditions de rception radiofrquence rencontres en pratique. Par ailleurs, la dcoupe des trames (identifiant de lavion, identifiant du vol, texte transmis) est actuellement embryonnaire et na que pour vocation de faciliter la prise en main du logiciel de dcodage par lutilisateur nophyte qui pourrait tre rebut par la lecture des squences brutes doctets. Toujours suivant les prconisations de http:// w w w.scancat.com/Code-30_html_ Source/acars.html, aprs avoir valid les 5 octets de synchronisation et den-tte (SOH, ASCII 0x01) en dbut de trame, nous extrayons lidentifiant de lavion (octets 6 12), lidentifiant de dbut de texte (STX, code ASCII 0x03) avant de rechercher lidentifiant du vol (octets 22 27), qui sont les informations les plus utiles. Ensuite, dans le meilleur des cas, si le message est dcodable, les caractres ASCII affichables au-del du 28me octet sont fournis.

Figure 15 : Dcodage par un bloc gnuradio-companion implmentant les algorithmes de dcodage dcrits dans le texte dune trame ACARS enregistre dans un fichier audio chantillonn 48 kchantillons/s. Remplacer le fichier audio par la sortie du bloc osmosdr pour un traitement en temps rel (blocs en gris fonc) des donnes permet de bien identifier le dbut de transmission, mais le dcodage du message choue souvent, probablement du fait dun mauvais ajustement des seuils.

Un exemple de dcodage en temps rel du flux de donnes transmis par le bloc dcrit dans ce paragraphe est (tout dabord la valeur des octets reus, puis leur interprtation dans le code ASCII pour les caractres affichables) :
63 70 5c 72 27 7d 04 09 5c 42 43 26 7e 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 2b 2a 16 16 01 47 2e 45 49 2d 44 54 4e 15 48 31 35 02 44 35 33 43 41 5a 30 32 34 33 23 44 46 42 33 2c 33 39 2c 30 35 39 2c 30 34 35 39 39 2c 30 31 33 36 2f 56 31 30 32 2c 31 32 2c 32 32 32 2c 32 39 32 2c 30 33 2c 30 31 2c 30 30 30 30 30 2f 56 32 30 32 2c 30 38 2c 30 38 31 2c 30 36 39 2c 30 30 2c 30 30 2c 30 30 30 30 30 2f 56 33 30 32 2c 30 36 2c 31 34 36 2c 33 31 32 2c 30 36 32 32 2f 56 34 31 30 2c 30 36 2c 32 32 33 2c 30 32 35 2c 30 36 32 31 2f 56 35 30 30 2c 30 30 2c 30 30 30 2c 30 30 30 2c 30 30 30 30 2f 56 36 30 30 2c 30 30 2c 30 30 30 2c 30 30 30 2c 30 30 30 30 2f 56 37 30 34 31 2c 30 38 37 2c 30 30 30 36 31 2c 32 32 32 32 32 32 32 32 32 32 32 47 31 31 2f 56 38 30 34 31 2c 30 38 36 2c 30 30 30 38 31 17 24 3e 7f cp\r}\BC&~+*G.EI-DTNH15D53CAZ0243#DFB3,39,059,04599,0136/V102,12,222,292,03,01,00000/V202,08,081,069,00, 00,00000/V302,06,146,312,0622/V410,06,223,025,0621/V500,00,000,000,0000/V600,00,000,000,0000/V7041,087,00 061,22222222222G11/V8041,086,00081$>

Nous constatons que la squence acquise est trop longue avant le prambule de 0x2b 0x2a 0x16 0x16, avec la squence des 0x7f qui correspond aux octets 2400 Hz pour la synchronisation du rcepteur avec lmetteur. Nanmoins, le dcodage seffectue bien, avec lidentification dune trame mise par EI-DTN, un A320 de Alitalia qui cette fois volait au cours du trajet AZ0243 entre Londres et Milan (cohrent avec une rception depuis Paris vers 21h15 alors que cet avion est suppos partir, en labsence de retard, de Londres 19h50 pour arriver Milan vers 21h45). Ici encore, le contenu du message semble cohrent mais incomprhensible. Ainsi, sans tre parfaite, notre implmentation du dcodage en temps rel des trames ACARS sous gnuradio-companion permet dobtenir lidentification de la majorit des avions passant proximit du rcepteur, et dans certains cas des messages aussi longs que :
23

http://www.qsl.net/g4hbt/zips/krcrs12.zip

28

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

Ainsi, le message brut :


2b 2a 16 16 01 32 2e 2e 48 42 4a 4b 4c 15 31 37 30 02 4d 33 33 37 31 2f 32 37 32 37 31 39 33 34 4c 53 47 47 45 4e 5a 56 2f 4e 20 2f 32 36 32 2f 20 34 33 2f 33 30 32 2f 2d 20 33 39 2f 41 55 +*2..HBJKL170M33AGS0871POA01GS0871/27271934LSGGENZV/N47 17.1/E 41 34 54 6 47 53 30 38 37 31 50 4f 41 30 31 47 53 30 38 37 20 31 37 2e 31 2f 45 20 20 36 20 31 2e 35 4f 52 50 2f 31 35 03 43 6a 7f 1.5 /262/ 43/302/- 39/AUTORP/15Cj

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

se traduit en :
Aircraft=..HBJKL STX Seq. No=4d 33 33 41 M33A Flight=GS0871 POA01GS0871/27271934LSGGENZV/N47 17.1/E 6 1.5 /262/ 43/302/- 39/AUTORP/15ETX

soit un Falcon 2000 rpertori par les autorits suisses24 comme bas Genve, entendu vers 21h45 depuis Besanon, avec lidentifiant de vol GS0871, de nouveau fournissant des coordonnes GPS en accord avec la localisation du rcepteur. Le lecteur possdant entre 15 et 20 millions de dollars pourra considrer de sacheter ce jouet doccasion. Dun autre ct, un tel investissement permet de raliser une matrice de 1000*1000 rcepteurs EZCAP et ainsi de former un rcepteur RADAR balayage de faisceau (http://www.haarp.alaska.edu/), autrement plus intressant quune bote de conserve volante. Par ailleurs, on notera une certaine cohrence dans la squence des messages :
Mon Aug 27 22:03:31 Aircraft=.PH-XRX STX Seq. No=53 35 32 41 Flight=HV5078 ETX Mon Aug 27 22:04:30 Aircraft=.PH-XRX STX Seq. No=53 35 33 41 Flight=HV5078 ETX Mon Aug 27 22:09:00 Aircraft=.PH-XRX STX Seq. No=53 35 35 41 Flight=HV5OHG ... 2012 S52A 2012 S53A 2012 S55A

des arguments (valeurs numriques, chanes de caractres) et nous dsirons exploiter cette possibilit. Tout commence par la dfinition des arguments et lajout des prototypes associs dans linterface graphique (rpertoire grc), i.e. le fichier XML descriptif du bloc. Les balises dfinissant un passage de variable sont <param> ... </param> qui prennent comme champs le nom de la variable associe <key> et la nature de cette variable, par exemple un flottant <type> real </type>. Cette dclaration de variable doit imprativement se situer avant le paramtre <sink> sous peine dobtenir un message derreur (cryptique) au chargement du bloc. Il reste dans le fichier XML passer la variable au programme C++ en compltant la mthode <make> par le paramtre, dans notre cas acars. decodeur($seuil) (avec seuil le nom de la variable tel que dfinit dans key). Du point de vue de la dclaration de la classe (rpertoire include), la signature de la fonction dentre ainsi que celle du constructeur de la classe doivent tre adaptes pour contenir largument acars_make_decodeur (float seuil1); dans toutes ses occurrences. Finalement, le constructeur, au niveau de limplmentation de la classe C++ elle-mme (rpertoire lib), reoit largument sous forme de
acars_decodeur::acars_decodeur (float seuil1). Dans notre cas, une

indiquant que cette information (S52A, S53A, S55A) est convenablement dcode. Si le lecteur, en lisant ce code et en le mettant en uvre, laisse tourner son PC la nuit dans lespoir de recevoir le message dun avion excessivement en retard, ou se rveille le matin en sursaut pour savoir combien de passages daronefs il a enregistr - le mal est fait, le virus de la rception de signaux radiofrquences a infect une nouvelle cible, le seul remde est de... lire le code pour lamliorer et augmenter ses performances de dcodage.

consigne de seuillage est ainsi transfre depuis linterface graphique de gnuradio-companion vers la classe C++ sans ncessiter de recompilation de la bibliothque (bloc). Un exemple simple de passage dun unique paramtre est facilement accessible dans larchive de gnuradio sous
gnuradio/gr-digital/*/digital_ diff_decoder_bb.* : la recherche de

5.3 Passage de paramtres linstanciation


Le dernier point qui peut faciliter la vie du dveloppeur est de pouvoir changer, en remplissant le champ correspondant dans le bloc gnuradio-companion, des paramtres des blocs utiliss dans lapplication, sans tre oblig de recompiler la bibliothque correspondante. Nous constatons que de nombreux blocs acceptent
24

loccurrence du terme modulus permet de se retrouver dans le cheminement de la variable entre les divers fichiers dfinissant le bloc, et de sen inspirer pour notre propre application (Fig. 16, page suivante).

http://www.bazl.admin.ch/fachleute/luftfahrzeugregister/index.html?lang=en

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

29

LAbO

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Figure 16 : Le bloc complt par le passage de deux arguments que sont une valeur de seuil (flottant) et le nom de fichier denregistrement des donnes acquises (chane de caractres). Nous constatons dans lxterm que les donnes sont bien stockes dans lemplacement annonc, et les valeurs sont cohrentes avec celles affiches par gnuradio-companion.

5.4 Passage dynamique de paramtres


Le passage de paramtres selon la mthode propose ci-dessus dfinit la valeur de largument (seuil) au moment du lancement de lapplication gnuradiocompanion par passage de paramtres au constructeur de la classe associe au bloc. Une fois ce paramtre fourni, il est impossible de le modifier depuis lapplication en cours dexcution. Cependant, de nombreux blocs permettent de faire varier des variables depuis des composants graphiques reprsentant des ascenceurs (sliders) : comment font-ils ? Un argument additionnel la dclaration du bloc dans le fichier XML permet de dfinir une mthode pour mettre jour une variable membre lorsque le paramtre qui lui est associ dans linterface graphique change de valeur : dans
Figure 17 : Le bloc de dcodage des trames ACARS accepte dsormais la dfinition du paramtre seuil au moyen dun ascenceur (bloc slider) avec modification de la valeur en cours dexcution. Dans cet exemple, nous constatons quun ascenceur associ la variable threshold a t dfini avec une valeur par dfaut de 150 (tel quannonc dans le terminal en bas de gnuradio-companion), et changer la valeur dans longlet associ de linterface graphique change bien la valeur du paramtre exploit lors du dcodage des trames.

30

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SOFTWARe DeFIneD RADIO SDR)

le fichier contenu dans le rpertoire grc, nous compltons la dfinition du bloc par le nom de la mthode appele pour la mise jour du paramtre (argument callback)

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

<make>acars.decodeur($seuil,$filename)</make> <callback>set_seuil($seuil)</callback> <param> <name>Threshold</name> <key>seuil</key> <type>real</type> </param>

dont la signature associe est dclare dans le fichier de dfinition de linterface de la classe (rpertoire include) :
public: ~acars_decodeur (); void set_seuil(float seuil1);

et finalement, dans la bibliothque, nous implmentons la mthode (setter) qui modifie le contenu de la variable membre (prive) :
void acars_decodeur::set_seuil(float seuil1) {printf("new threshold: %f\n",seuil1);fflush(stdout);_seuil=seuil1;}

Ainsi, nous vrifierons que chaque fois que la valeur du paramtre seuil est modifie en faisant glisser un ascenceur dans linterface graphique, la valeur est bien modifie dans le bloc de traitement de linformation correspondant (Fig. 17). Larchive finale de ce dveloppement (Fig. 18 et 19, page suivante), incluant tous les concepts dvelopps dans cet article, est disponible http://jmfriedt.free.fr/gr-acars.tar.gz ou sur le site de CGRAN www.cgran.org/wiki/ACARS.

Conclusion
Nous nous sommes efforcs de proposer une dmarche de travail pour exploiter un rcepteur radiofrquence fournissant un flux de donnes I et Q en vue de dcoder des trames numriques. Nous nous sommes en particulier concentrs sur les priphriques faible cot centrs sur le composant E4000 coupl au convertisseur analogique-numrique RTL2832U. Au-del de la simple utilisation des blocs de traitement de signaux fournis avec loutil gnuradio, nous avons identifi le cheminement du flux de donnes afin de dvelopper nos propres blocs de traitement. Nous avons dmontr la capacit implmenter des traitements en temps rel sur le flux dinformations issu du rcepteur en prototypant dans un premier temps sous GNU/Octave sur des enregistrements, avant de convertir lalgorithme en C pour inclusion dans gnuradio.

Figure 18 : Exemple de trames ACARS acquises au moyen dun rcepteur EZCAP muni dune antenne forme dun bout de fil de cuivre maill de 50 cm de longueur. Cette activit rend les heures dattente dans les aroports beaucoup plus ludiques, ici Athnes (Grce).

Parmi les perspectives, lexploitation sur des signaux plus intressants que sont le GPS25 ou le GSM serait ambitieuse, mais certainement source de nombreuses dcouvertes. Sans relation directe avec cette prsentation, un collgue dun des auteurs (JMF) nous faisait remarquer rcemment comment lpoque de Capitaine Crunch et de la naissance dApple devait tre une poque bnie du hack. Nous profitons de ces pages pour exprimer notre dsaccord avec cette nostalgie : la disponibilit de puissances de calcul quasi-infinies, pour un cot abordable pour une majorit de la population

25 http://michelebavaro.blogspot.fr/2012/04/spring-news-in-gnss-and-sdr-domain.html mais surtout http://www.gnss-sdr.org/documentation/gnss-sdr-operation-realtek-rtl2832uusb-dongle-dvb-t-receiver dmontrent le rsultat impressionnant dutiliser un rcepteur de tlvision numrique terrestre pour recevoir des signaux issus de satellites situs une distance de 20000 km.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

31

LAbO

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Figure 19 : Analyse des trames ACARS obtenues en temps rel par notre module gr-acars : le site web radarvirtuel.com/index-fr.html valide la prsence, proximit de Besanon (position de lantenne rceptrice), dun avion de Transavia, tandis que le site airliners.net associe une immatriculation davion (PH-RXA) un exploitant. Les informations acquises par ACARS sont donc cohrentes avec les autres donnes disponibles sur les sites web associs au suivi du trafic arien, et fournissent un complment idal au dcodeur ADS-B prsent au dbut de ce document.

dEurope occidentale et dAmrique du Nord, un mode de communication rapide et sans censure pour les domaines et les rgions qui nous concernent, et des documentations ou chantillons de composants lectroniques facilement disponibles, font de lpoque actuelle une priode au moins aussi excitante pour le hack que lpoque des blue box et autres activits de phreaking [14], comme nous avons tent de le dmontrer dans cet expos. La lgende du dtournement dun sifflet pour communiquer avec les routeurs tlphoniques est certes attractive, mais il ny a aucun doute que cette dcouverte fortuite tait prcde dheures danalyses des protocoles de communication et dtudes fastidieuses des conventions de communication des rseaux tlphoniques dantan (John Draper ntait-il pas ingnieur en dehors de ses activits de comprhension des systmes tlphoniques) : un bon hack est impossible sans une comprhension dtaille de la technologie sous-jacente. Nous osons copier ici les paroles reproduites du site de Wikipdia26, sans en vrifier lorigine, pour leur sagesse27 :

Remerciements
D. Bodor nous a informs de lexistence des rcepteurs DVB base de E4000+RTL2832U et de lengouement quils ont suscit dans la communaut des dveloppeurs de SDR. Les interlocuteurs de la mailing list osmocom-sdr ont lev un certain nombre dincertitudes sur les donnes techniques des rcepteurs radiofrquences base de RTL2832U et E4000. Le gouvernement quatorien mrite toute notre gratitude, ne serait-ce que pour son hbergement de http://gen.lib.rus.ec/, o nous obtenons la majorit des documents de la bibliographie, et autres actions politiques qui dpassent le cadre de cet article. J. Boibessot (Armadeus Systems) et E. Carry (FEMTOST) ont, par leurs corrections lors dune relecture, amlior le manuscrit.

I dont do that. I dont do that anymore at all. And if I do it, I do it for one reason and one reason only. Im learning about a system. The phone company is a System. A computer is a System, do you understand? If I do what I do, it is only to explore a system. Computers, systems, thats my bag. The phone company is nothing but a computer.

26 27

http://en.wikipedia.org/wiki/John_Draper http://www.slate.com/articles/technology/the_spectator/2011/10/the_article_that_inspired_steve_jobs_secrets_of_the_little_blue_.single.html (lu en septembre 2012).

32

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA RCePTIOn RADIOFRQUenCe DFInIe PAR LOGICIeL (SDR)

Rfrences
[1]  K. Borre, D.M. Akos, N. Bertelsen, P. Rinder & S.H. Jensen, A Software-Defined GPS and Galileo Receiver: A Single-Frequency Approach, Birkhuser Boston (2007) ainsi que les transparents http://kom.aau.dk/project/ softgps/ et en particulier http://kom.aau.dk/project/softgps/GNSS_SummerSchool_DGC.pdf [2]  J. Hamkins & M.K. Simon, Autonomous Software-Defined Radio Receivers for Deep Space Applications, Deep Space Communications and Navigation Series Vol. 9, disponible http://descanso.jpl.nasa.gov/Monograph/ series9/Descanso9_Full_rev2.pdf [3]  P.B. Kenington RF and baseband techniques for software defined radio Artech House (2005) [4] L  a littrature sur SDR pullule douvrages plus ou moins intressants. Parmi ceux que nous avons trouv de peu dintrt car loin de la pratique, W. Tuttlebee, software defined radio - enabling technologies Wiley (2002), ou encore M. Dillinger, K. Madani, N. Alonistioti, Software Defined Radio Architectures, Systems and Functions Wiley (2003), que le lecteur pourra viter sans craindre de rater trop dinformations. [5]  J.-M Friedt & S. Guinot, La rception dimages mtorologiques issues de satellites : principes de base, GNU/Linux Magazine France, Hors-Srie 24 (Fvrier 2006), disponible http://jmfriedt.free.fr/LM_sat1.pdf [6]  Note dapplication AN2668, Improving STM32F101xx and STM32F103xx ADC resolution by oversampling, ST Microelectronics, 2008 [7]  D.J. Mudgway, Uplink-Downlink - A History of the Deep Space Network, 1957-1997, NASA SP-2001-4227, The NASA History Series (2001), disponible partir de history.nasa.gov/SP-4227/Uplink-Downlink.pdf [8]  M.K. Simon, Bandwidth-Efficient Digital Modulation with Application to Deep-Space Communications, Deep Space Communications and Navigation Series Vol. 3, disponible http://descanso.jpl.nasa.gov/Monograph/ series3/complete1.pdf [9] T  .G. Thomas & S. Chandra Sekhar, Communication Theory, Tata Mcgraw Hill Publishing (2006) [10]  N. Foster, Tracking Aircraft With GNU Radio, GNU Radio Conference (2011), disponible http://gnuradio.org/redmine/attachments/download/246/06foster-adsb.pdf [11]  T. McDermott, Wireless Digital Communications: Design and Theory 2nd Ed., Tucson Amateur Packet Radio Corporation - TAPR (1998) [12]  Agilent, Digital Modulation in Communications Systems - An Introduction, Application Note 1298 disponible cp.literature.agilent.com/litweb/ pdf/5965-7160E.pdf, ou M. Steer, Microwave and RF design - a systems approach, SciTech Publishing, Inc (2010) dont le premier chapitre est disponible http://www.ece.ucsb.edu/yuegroup/Teaching/ECE594BB/ Lectures/steer_rf_chapter1.pdf [13]  J.-M Friedt, Auto et intercorrlation, recherche de ressemblance dans les signaux : application lidentification dimages floutes, GNU/Linux Magazine France 139 (Juin 2011), disponible http://jmfriedt.free.fr/ [14]  S. Wozniak & G. Smith, iWoz: Computer Geek to Cult Icon: How I Invented the Personal Computer, Co-Founded Apple, and Had Fun Doing It, W. W. Norton & Company (2007)

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

HORS-SRIE 63

GNU/LInuX MAgAZInE

Le hard est de retour ! Dbutez


en et

lectronique numrique Systmes embarqus


Partez de rien et montez en puissance : Arduino / Atmel AVR Ti Launchpad / MSP430 STM 32 Discovery / Cortex-M4 ACME Aria / ARM9 Raspberry Pi / ARM11
Sous rserve de toutes modifications.

Un magazine complet pour

s'initier comprendre progresser et explorer


chez votre marchand
33

26 octobre
GNU/Linux Magazine N 1 5 3 de France journaux

w w w. g n u l i n u x m a g.com

En COUVeRTURe

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Systemd vainqueur de Upstart et des scripts System V?

par Jrme Delamarche [Consultant indpendant en technologies open source]

Aprs plus de 30 ans de service (!), le vnrable processus init et ses scripts de service disparaissent petit petit des systmes Unix et de nos distributions Linux prfres. Si la technologie Upstart est connue des adeptes dUbuntu, quel sera le remplaant sur RedHat, Debian et les autres? systemd trs probablement... Lobjectif de cet article est de vous prparer la migration vers cette nouvelle technologie.

1 Introduction
Vous conna issez cer ta inement les scripts dits System V ou de service ? Vous savez, ce sont ces scripts shell, situs sous /etc/init.d/ et dont lappel avec les paramtres start ou stop produit les messages : Dmarrage de .... [OK] ou Arrt de ... [OK]. Ces scripts, ainsi que leur mcanique de lancement via /etc/rc, sont un hritage du vnrable Unix System V qui date de 1983. Cette architecture est simple, mais certains la trouvent lente, peu robuste et limite, aussi depuis quelques annes deux alternatives ont merg au sein des principales distributions Linux. Dun ct, on trouve les partisans de Upstart (Ubuntu) et de lautre les supporters de systemd (Fedora, Mandriva, OpenSuSE et bientt RedHat et Debian). Notons que lauteur de systemd Lennart Poettering [LPOE1] est employ chez RedHat... ceci explique cela.

Il ne sagit pas ici de comparer ces deux successeurs du vnrable init, mais dexpliquer le fonctionnement de systemd. Pourquoi ce choix partial ? Parce que systemd me semble mieux document, mieux architectur et surtout plus universel au vu du nombre de distributions qui lont choisi ou qui vont ladopter.

Pourquoi systemd est-il meilleur que init? (voir [LPOE2])


Dans un souci de rationalisation et doptimisation, systemd va raliser des tches qui taient auparavant laisses au bon-vouloir du dveloppeur des scripts System V. Par exemple, dornavant, la gestion et le contrle des PID des processus de service ainsi que ceux de leurs enfants sont la charge de systemd. De mme pour les logs. Systemd va aussi jouer le rle de coordinateur et darbitre pour grer dpendances et conflits. Pour amliorer les performances du dmarrage, systemd adopte plusieurs techniques astucieuses: tout dabord,

connaissant larbre de dpendances des services, il est naturellement capable de parallliser les lancements de processus (on peut lancer A et B sils ne dpendent pas lun de lautre, mme indirectement). Mais au-del, systemd peut lancer en parallle des processus interdpendants! Comment cela? Systemd va anticiper et crer une socket Unix pour tout service dmarrer. Ainsi, les clients dun service (cest dire les services dpendants) vont se connecter dessus alors que le service rel nest peut-tre pas encore actif. Quand celuici le sera, systemd lui passera la socket, ainsi les clients bloqus pourront tre servis!

2 Concepts et architecture de systemd


Il faut imaginer chaque unit comme un objet part entire, possdant
systemd sappelle une unit (unit).

Le composant de base gr par

34

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

Systemd vainqueur de Upstart et des scripts System V?

SySTemD

gnralement sa propre configuration. Les anciens scripts de service peuvent tre rcrits sous forme dunits pour systemd, mais ce ne seront pas les seuls!

(tableau non exhaustif)


Nom de lunit prdfinie Description

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

2.1 Types dunits


Les units sont des objets typs qui possdent un tat, par exemple actif, inactif ou en erreur (active, inactive, failed). Les types dunits supports sont:
Nom du type dunit Description

basic.target ctrl-alt-del.target

dfinit des tches dclencher trs tt. que faire quand lutilisateur appuie sur Control-Alt-Suppr (lien symbolique vers reboot.target). lien symbolique vers multi-user. target (quivalent au runlevel 3 de RedHat/Fedora) ou graphical.target (quivalent au runlevel 5). Cest lunit dclenche en premier. units invoques au dmarrage ou lors de larrt du systme ou quand lordre correspondant est donn par la commande systemctl (voir 4).

default.target

service

permet de dclencher et superviser des processus lancs travers des scripts System V ou directement par systemd. de type Unix, FIFO ou INET, elle est associe un service. Par exemple, un accs la socket nscd.socket va dmarrer le service nscd.service (voir plus haut le principe de lanticipation par cration de sockets Unix).

emergency.target, rescue.target halt.target, poweroff.target, reboot.target, shutdown.target sysinit.target

socket

units invoques trs tt lors du dmarrage et indpendamment du runlevel. Lactivation du LVM en est un exemple. (o X prend les valeurs 0 6) permet de simuler les changements de runlevel. Ces units sont en fait des liens symboliques vers poweroff.target (niveau 0), rescue.target (niveau 1), multi-user.target (niveaux 2,3,4), graphical.target (niveau 5) et reboot.target (niveau 6). pour le montage des systmes de fichiers et lactivation du swap. pour grer correctement les dpendances entre les services et le rseau.

runlevelX.target

mount automount path

gestion du fichier /etc/fstab. pour la gestion des systmes de fichiers auto-monts. permet dactiver dautres services quand des fichiers ou des rpertoires sont modifis. ventuellement les rpertoires peuvent tre crs par systemd. pour regrouper des units logiquement ou pour dfinir des units prdfinies dites units spciales (voir ci-dessous). pour activer des units sur le dclenchement de timers. pour permettre un save/rollback pendant des changements de configuration de service. pour lactivation des zones de swap (pas utilis sur Fedora 17).

target

local-fs.target, remote-fs.target, swap.target network.target

timer snapshot swap

2.3 Organisation et syntaxe des fichiers de configuration


Si on conoit bien le besoin dimiter le comportement de
init, quoique le nombre des units spciales soit trs cons-

Nous allons voir que chaque unit possde son propre fichier de configuration, mais le type de lunit sera donn par le suffixe du nom du fichier de configuration. Par exemple, le fichier sshd.service sera associ une unit de type service.

quent, il faut maintenant se reprsenter concrtement comment sont conues ses fameuses units.
Systemd est compos de nombreux excutables situs sous /usr/lib/systemd/. Dailleurs le premier processus, lanc par le noyau au dmarrage, est /usr/bin/systemd qui nest autre quun lien symbolique vers /usr/lib/systemd/ systemd. Si vous ne vous en doutiez pas dj, vous noterez ds prsent que larchitecture de systemd fait un usage

2.2 Units prdfinies


Mais pour pouvoir se substituer au vieil init, il a fallu concevoir des units prdfinies (ou units spciales), certaines correspondant directement la valeur du champ action des lignes du fichier /etc/inittab :

abondant des liens symboliques... La configuration est situe dans le rpertoire /etc/ systemd/ et le fichier de configuration principal va sappeler /etc/systemd/system.conf.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

35

En COUVeRTURe

Pour connatre lemplacement des fichiers de configuration de systemd, il est possible dutiliser la commande suivante:
# pkg-config systemd --variable=systemdsystemconfdir /etc/systemd/system

# pkg-config systemd --variable=systemdsystemunitdir /usr/lib/systemd/system

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Notes
Note1 : systemd peut tre invoqu par un utilisateur avec loption --user, dans ce cas, son fichier de configuration principal est /etc/systemd/user.conf, mais nous occulterons cette possibilit ici. Note2 : Sur la distribution Fedora 17, utilise ici comme exemple, les rpertoires /bin, /sbin et /lib sont en fait des liens symboliques sur /usr/bin, /usr/sbin et /usr/lib. Le fichier /etc/systemd/system.confest un fichier la .INI, contenant une rubrique [Manager] et des options globales, dont les principales sont listes dans ce tableau:
Paramtre Description Valeur par dfaut

Si les fichiers qui sont sous /etc/systemd/system/ sont en fait des liens symboliques sur leurs homonymes situs sous /lib/systemd/system/, certains rpertoires existent avec le mme nom la fois sous les rpertoires /etc/ systemd/system/ ET /lib/systemd/system/, et dans ce cas leur contenu diffre. Laffichage de la valeur de la variable systemdsystemunitpath avec la commande pkg-config montre bien que le rpertoire /etc/systemd/ system/ est prioritaire. Un fichier de configuration dunit contient les rubriques suivantes:
Nom de la rubrique Description

[Unit]

dcrit le service et les rgles de dpendances laide des paramtres:

Description, Before, After, Requires, Requisite, Wants, Condition*.


[Install] dcrit ce quil faut faire quand on invoque systemctl enable | disable. Par exemple, le paramtre WantedBy=xxxx indique quil faudra crer un lien symbolique dans le rpertoire /etc/systemd/ system/xxxx.wants/. Also indique des units additionnelles installer en plus.

LogLevel LogTarget

dfinit le niveau de verbosit.

info

destination des messages de syslog logs. Une valeur usuelle est journal, qui exploite un processus supplmentaire (voir 3.2). honore les montages de sys- yes tmes de fichiers lists dans /etc/fstab. honore lactivation des zones de yes swap listes dans /etc/fstab. choix du cgroup. cpu

MountAuto

Puis, selon le type de lunit, des sections supplmentaires et leurs lots de paramtres seront ncessaires.

MountSwap DefaultControllers

2.4 Exemples de configuration


tout seigneur tout honneur, examinons le contenu du fichier /etc/systemd/system/default.target qui est le nom de la premire unit lance par systemd (pour information, je suis un adepte de la commande readlink qui permet de connatre le nom final du fichier rfrenc par une suite de liens symboliques):
# readlink -f /etc/systemd/system/default.target /lib/systemd/system/graphical.target # cat /etc/systemd/system/default.target [Unit] Description=Graphical Interface Documentation=man:systemd.special(7) Requires=multi-user.target After=multi-user.target Conflicts=rescue.target AllowIsolate=yes [Install] Alias=default.target

Certaines options peuvent tre surcharges en passant des options au noyau ou sur la ligne de commandes systemd. Par exemple, en cas de problme, systemd propose un mode pas--pas pour permettre la rsolution des problmes si vous lui passez le paramtre systemd.confirm_ spawn=1 comme option du noyau, ou --confirm-spawn sur sa ligne de commandes.
systemd analyse ensuite le contenu du fichier bien nomm /etc/systemd/system/default.target qui, sur la Fedora 17 lance en mode graphique, est un lien symbolique vers /lib/systemd/system/runlevel5.target. Enfin du concret! Nous pouvons examiner le contenu de ce fichier et commencer explorer la syntaxe des fichiers de configuration des units.

Notez que sur votre distribution, pour connatre lemplacement des fichiers de configuration des units, il est possible dutiliser la commande suivante:

Nous retrouvons bien les sections [Unit] et [Install] dont nous avons parl au 2.3. Le paramtre Requires= indique que lunit multi-user.target doit tre active pour

36

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

Systemd vainqueur de Upstart et des scripts System V?

SySTemD

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

que default.target soit considre comme active. Le paramtre After= prcise quil faut attendre la fin de lexcution de lunit multi-user.target avant de finir lexcution de default. target (il existe aussi un paramtre Before=, mais en labsence de prcision sur lordonnancement, les excutions sont paralllises). Le paramtre Conflicts= indique que lunit default.target ne doit pas tre lance si rescue.target est dj active. Lunit rescue.target correspond au runlevel 1, il est normal de ne pas lancer le mode multi-utilisateur et encore moins linterface graphique! Le paramtre AllowIsolate= est un hack: il permettra de faire en sorte quon puisse imiter le changement de niveau dexcution comme on le faisait avec init. Dans le cas dun changement de runlevel, donc, tous les processus qui ne seront pas grs par lunit default.target ou ses dpendances seront arrts. Le paramtre Alias= de la rubrique [Install] indique que lors de lactivation de cette unit (dont le vritable nom est runlevel5.target), il faudra crer un alias sous la forme dun lien symbolique nomm default.target! Eh oui: autant dcrire tous les liens symboliques dans des fichiers de configuration et laisser les outils fournis avec systemd grer correctement ces liens. Reprenons : default.target doit tre active aprs multi-user.target. Que fait cette unit?
# cat /lib/systemd/system/multi-user.target [Unit] Description=Muti-User Documentation=man:systemd.special(7) Requires=basic.target Conflicts=rescue.service rescue.target After=basic.target rescue.service rescue.target AllowIsolate=yes [Install] Alias=default.target

cette unit dpend de basic.target, mais un moment donn, il faudra bien lancer des processus! Notons que la rubrique [Install] dfinit un Alias qui porte le mme nom que celui dfini par lunit graphical.target: ce nest pas un problme car lunit graphical.target se jouant aprs multi-user.target, le lien symbolique default.target pointera bien vers la bonne unit. En continuant lexamen des units selon leurs dpendances, on constate que
basic.target dpend de sysinit.target et sockets.target. La configuration de sysinit.target contient un nouveau paramtre intressant:
[Unit] ... Wants=local-fs.target swap.target

On se doute quil va falloir dabord activer les systmes de fichiers locaux ainsi que le swap avant de raliser dautres tches, mais ici, Wants= indique que lunit sysinit.target sera active mme si lune des units dont elle dpend choue lors de son activation. Ce comportement est diffrent du Requires= qui stipule que lunit nest active que si toutes les units dont elle dpend sont actives avec succs (cest une forme de transaction !). Parfois, une unit peut dpendre de trs nombreuses autres units, ce qui provoquerait lcriture de directives Wants= ou Requires= assez fastidieuses avec le souci de devoir modifier ces lignes chaque fois que les dpendances sont modifies. Pour viter cela, systemd permet dexternaliser les dpendances dune unit en permettant lutilisation de rpertoires associs des liens symboliques (encore !). Le principe est le suivant (nous le dcrivons pour la directive Wants=, il se transpose aisment pour la directive Requires=): Prenons lexemple de lunit sysinit.target, elle dpend de local-fs.target et swap.target , comme indiqu par son fichier de configuration, mais ce nest pas tout! Comme il existe un rpertoire nomm /etc/systemd/system/ sysinit.target.wants/, lunit sysinit.target dpend aussi de toutes les units dont le nom apparat dans les liens symboliques situs dans ce rpertoire:
# cd /etc/systemd/system # ls -l sysinit.target.wants ... lvm2-monitor.service -> /usr/lib/systemd/system/lvm2-monitor.service ... mdmonitor-takeover.service -> /usr/lib/systemd/system/mdmonitor-takeover.service

Les dpendances se rglent donc simplement coups de cration et destruction de liens symboliques. Rle parfaitement rempli par la commande systemctl que nous verrons dans un instant. Prenons un autre exemple: comment est lanc le dmon sshd ? Il est dcrit par lunit /lib/systemd/system/sshd.service qui est rfrence par un lien symbolique situ sous /etc/systemd/system/multi-user.target.wants/. Le contenu du fichier sshd.service est:
[Unit] Description=OpenSSH server saemon After=syslog.target network.target auditd.service [Service] EnvironmentFile=/etc/sysconfig/sshd ExecStartPre=/usr/sbin/sshd-keygen ExecStart=/usr/sbin/sshd -D $OPTIONS ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.target

Vous commencez comprendre le mcanisme? On nage en pleine rcursivit:

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

37

En COUVeRTURe

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Oui, un service dispose dune nouvelle rubrique nomme [Service] dont les paramtres sont explicites. Toutefois, il manque ici le paramtre Type= qui indique comment lancer le service. La valeur par dfaut est simple pour indiquer que le processus nomm par ExecStart= est le processus principal du service, mais les autres possibilits sont : forking, dbus, oneshot, idle et notify (voir la documentation man systemd.service). Remarquez aussi la ligne de commandes qui permet de faire un reload du dmon : la variable $MAINPID est gre par systemd et aura pour valeur le PID de sshd. Dans la configuration de lunit sshd.service, on trouve aussi la directive WantedBy= qui indique la dpendance entre ce service et lunit multi-user.target, ce qui ncessitera la cration dun lien symbolique dans
/etc/systemd/system/multi-user. target.wants/ lors de linitialisation

grer, ce qui est videmment viter. Les modles dunits prennent tout leur sens alors: si systemd doit activer une unit dont le nom est getty@tty1.service et que ce nom dunit nexiste pas sous /lib/systemd/system/, alors, cause de la prsence du caractre @ dans le nom de lunit, systemd va rechercher une unit dont le nom est getty@. service. Comme cette unit existe, cest elle qui sera invoque et la chane tty1 qui faisait partie du nom de lunit initiale sera fournie sous forme de specifier accessible dans la configuration de lunit. Ce specifier se nomme %I (lire i majuscule. Il en existe dautres voir man systemd.unit). Voici un extrait du fichier getty@.
service sur Fedora17:
[Unit] Description=Getty on %I ... [Service] Restart=always RestartSec=0 TTYPath=/dev/%I ...

631 pour toutes les adresses IP de la machine, puis il crera une socket UDP (ListenDatagram) lcoute du port 631 en IPv4 uniquement. Dautres paramtres sont disponibles (voir man systemd.socket). Comme ultime exemple, nous allons prendre lexemple dun montage effectuer lors du dmarrage. Il marrive souvent de placer ce type de montage dans le vnrable /etc/rc.local, mais le faire grer par s y s t e m d est un gage de robustesse. Sur notre Fedora 17, le contenu du fichier media. mount est:
[Unit] Description=Media Directory Before=local-fs.target [Mount] : What=tmpfs Where=/media Type=tmpfs Options=mode=755,nosuid,nodev,noexec

des units. La configuration des services permet aussi dimiter la fonctionnalit du respawn propose par init. Avec systemd , la surveillance et la regnration dun processus de service est ralise par les directives Restart= (sur quel tat du processus fautil le relancer ?) et RestartSec= (au bout de combien de secondes faut-il le relancer ?). Regardez le contenu de la configuration de lunit getty@. service pour en avoir un exemple. Avez-vous remarqu la prsence du caractre @ dans le nom de lunit getty@.service ? Il sagit dune astuce lexicale propose par systemd pour permettre de crer des modles dunits (unit templates). En effet, vous savez quhabituellement vous disposez dun certain nombre de terminaux virtuels, chacun tant gr par une commande de la famille getty (par exemple, sur RedHat cette commande est /sbin/ ming etty voir dans le fichier /etc/inittab). Pour imiter ce comportement, il faudrait donc dfinir autant dunits que de terminaux virtuels

Ce qui permet davoir au dmarrage un rpertoire /media associ un systme de fichiers de type tmpfs. Comme vous le subodorez peut-tre dj, le nombre de paramtres possibles pour dfinir la configuration des units est trs important, ce qui fait la fois la richesse et la complexit de systemd!

Outre les services, au sens classique du terme, nous avons dit en prambule que systemd allait aussi grer les sockets afin dacclrer les lancements des processus inter-dpendants. Regardons la syntaxe de configuration dune unit de type Socket, par exemple cups.socket:
[Unit] Description=CUPS Printing Service Sockets [Socket] ListenStream=/var/run/cups/cups.sock ListenStream=631 ListenDatagram=0.0.0.0:631 [Install] WantedBy=sockets.target

2.5 Petite synthse


Rcapitulons en prenant comme exemple le dmarrage du systme: voir Figure 1, page suivante. Lorsque systemd est lanc par le noyau (1), il lit son fichier /etc/systemd/ system.conf (2), puis il examine la premire unit lancer: default.target (3) qui est en ralit un lien symbolique vers runlevel5.target (luimme lien symbolique vers graphical. target). Ce fichier contient une directive
After=multi-user .target, donc systemd

Nous constatons la prsence dune rubrique [Socket] contenant les paramtres de cration des sockets crer. Ici, systemd va crer une socket du domaine UNIX qui sappellera /var/run/ cups/cups.sock, puis une socket TCP (ListenStream) lcoute sur le port

cherche la configuration de cette unit (4) et linterprte. Mais il existe un rpertoire multi-user.target.wants (5), donc

38

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

Systemd vainqueur de Upstart et des scripts System V?

SySTemD

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

situs sous /run/log/journal/, mais il peut aussi rmettre les logs vers le dmon syslog (ou rsyslog dans notre cas) ou vers la Console systme. On peut lui indiquer des tailles limites de fichiers gnrer ou une taille maximale despace disque utiliser. Les fichiers de logs sont un format binaire, il faut utiliser la commande journalctl pour en afficher le contenu:
# journalctl

Figure 1

affiche le contenu des logs avec votre paginateur prfr, mais il est possible de limiter le nombre de lignes affiches avec loption -n (comme le fait la commande tail):
# journalctl -n 10

systemd parcourt ce rpertoire pour ac-

tiver les units qui y sont dcrites. On y trouve par exemple sshd.service, etc.

Note
Note: sur Fedora 17, le rpertoire /var/run est en fait un lien symbolique vers /run qui est le point de montage dun systme de fichiers de type tmpfs, donc rapide mais non persistant.

3 Gestion des processus et des logs


3.1 Gestion des processus
Par dfaut, systemd maintient automatiquement la relation entre PID et processus activs. Ainsi, le PID de notre dmon sshd prcdent est stock par systemd dans le fichier /var/run/sshd. pid. Mais pour les services dont la valeur de Type= est forked (alors que le type est simple pour sshd.service), systemd peut se tromper dans son analyse du processus principal. En effet, quand un service est de type forked, cela signifie que le processus lanc par systemd va lancer un ou plusieurs processus fils puis va se terminer. Sil a lanc plusieurs processus fils, le stockage de PID du processus fils principal est la charge du processus parent et il faut indiquer systemd dans quel fichier est stock ce PID. On fait pour cela un usage de la directive PIDFile= dans le fichier de configuration de lunit.

3.2 Gestion des logs


Dans le tableau du 2.3, nous avons montr les paramtres principaux de systemd dans le fichier /etc/systemd/ system.conf. Parmi ceux-ci, nous avons voqu LogTarget=. Sur Fedora 17, la valeur de ce paramtre est: journal. Cela indique systemd denvoyer tous les messages de log un nouveau dmon nomm systemd-journald luimme activ par systemd car dcrit par lunit systemd-journald.service. Ce processus est configur par le fichier /etc/systemd/systemd-journald.conf dont voici un extrait:
[Journal] ForwardToSyslog=yes MaxLevelSyslog=debug Compress=yes #SystemMaxUse= #ForwardToConsole=no

Enfin, laffichage peut tre filtr (comme le ferait grep !) en prcisant des valeurs spcifiques pour les champs des lignes de logs. Ces champs ont des noms prdfinis comme MESSAGE, PRIORITY, _PID, _HOSTNAME, _SYSTEMD_UNIT (voir man systemd.journal-fields). Par exemple, pour nafficher que les logs relatifs lunit sshd.service, on excute la commande:
# journalctl _SYSTEMD_UNIT=sshd.service

4 Comment faire comme avant, avec init?


Finalement, 30 ans aprs, Unix/Linux ne change pas radicalement: on peut grer systemd avec les commandes ln pour les liens symboliques et vi pour la configuration! Nanmoins, essayons dtre un peu plus productifs et vitons de rcrire des commandes qui existent dj. Si, comme moi, vous vous tes habitu aux commandes simples mais nanmoins utiles chkconfig et service, par quoi va-t-il falloir les remplacer ? Voici un petit tableau qui met en parallle vos commandes usuelles avec leur pendant la mode de systemd:

Le processus systemd-journald stocke les logs quil reoit dans des fichiers

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

39

En COUVeRTURe

Systemd vainqueur de Upstart et des scripts System V?

SySTemD

Remplacement de la commande chkconfig chkconfig sshd on chkconfig sshd off chkconfig sshd --list service sshd status service sshd start service sshd stop service sshd reload systemctl enable sshd.service systemctl disable sshd.service systemctl is-enabled sshd.service systemctl status sshd.service service sshd status systemctl start sshd.service service sshd start systemctl stop sshd.service service sshd stop systemctl reload sshd.service service sshd reload Remplacement des commandes init et telinit init 0 init 6 init 3 systemctl poweroff init 0 systemctl reboot init 6 systemctl isolaterunlevel3.target init 3 Choix du niveau dexcution au dmarrage valeur de initdefault dans /etc/inittab valeur du lien symbolique default.target

# systemctl dor | dot -Tsvg > fichier.svg

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Remplacement de la commande service

Conclusion
la lecture de cet article, peut-tre avez-vous eu la raction suivante : mais pourquoi avoir fait si compliqu alors que finalement init ne fonctionnait pas si mal que a ? [NDLR : ce serait plutt mais cest quoi ce #@$!& ? ]. Effectivement, je me suis aussi pos cette question et me la pose encore. Administrateur de serveurs Linux, je nai jamais connu de problme avec init et, si parfois, on peut considrer le temps de dmarrage comme plutt long, ce nest rien compar aux dlais de scans et de tests des Bios et firmwares des contrleurs de toutes sortes. Le passage vers systemd (ou upstart) ne se justifie pas, selon moi, sur de telles plates-formes. Vouloir faire la course entre distributions Linux, Mac OS X voire Windows (!), na aucun intrt pour des serveurs. Nanmoins, il semble que le pas soit pris et que, petit petit, les principales distributions Linux nous forcent ainsi nous adapter. Alors, avant de vous retrouver face une nouvelle version de votre Linux prfr o init et les scripts System V auront dfinitivement disparu, tudiez ds prsent le fonctionnement de systemd dont le primtre daction va encore saccrotre avec la future intgration de udev !

En rsum:
Fonctionnalit Activation dun service au dmarrage init (system V) commande chkconfig liens symboliques vers /etc/init.d/ commande service commande init systemd chkconfig et liens symboliques pour les scripts non encore migrs commande systemctl pour les processus pris en charge par systemd commande service ou commande systemctl commande init ou commande systemctl

Dmarrage ou arrt dun service Changement de niveau dexcution

Vous voyez lintrt de la nouvelle commande systemctl qui centralise toutes les oprations mais qui permet de raliser dautres oprations: - p our obtenir la liste de toutes les units (situes sous /lib/systemd/ system/) et leur tat courant:
# systemctl list-unit-files

Rfrences
[LPOE1] Blog de lauteur Lennart Poettering (http://0pointer.de/ blog/projects/systemd.html) [LPOE2] Comparaison faite par L.Poettering entre systemd, upstart et sysvinit (http://0pointer. de/blog/projects/why.html) [FEDORA] le wiki de systemd sur Fedoraproject.or (http://fedoraproject.org/wiki/Systemd)

- pour obtenir la liste et la description des units de type service:


systemctl list-units -t service

- si vous changez la configuration de systemd ou des units, la commande suivante permet de faire relire les fichiers par systemd:
# systemctl daemon-reload

- et si vous aimez les graphes bien touffus (et inexploitables !), vous pouvez gnrer une image reprsentant les dpendances entre toutes les units par:

40

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

Abonnez-vous !
Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Profitez de nos offres dabonnement spciales disponibles au verso !

conomisez plus de

03 67 10 00

Tlphonez

0 ou comman dez par le We b

au

Les 3 bonnes raisons de vous abonner :


N  e manquez plus aucun numro. R  ecevez GNU/Linux Magazine chaque mois chez vous ou dans

11

* Sur le prix de vente unitaire France Mtropolitaine

30%
Numros de
par ABONNEMENT :

GNU/Linux Magazine

votre entreprise.  conomisez 27,50 /an ! (soit plus de 3 magazines offerts !)

4 faons de commander facilement :


p  ar courrier postal en nous renvoyant le bon ci-dessous p  ar le Web, sur www.ed-diamond.com p  ar fax au 03 67 10 00 21 p  ar tlphone, entre 9h-12h et 14h-18h au 03 67 10 00 20

au lieu de 82,50 * en kiosque conomie : 27,50 *


* OFFRE VALABLE UNIQUEMENT EN FRANCE MTROPOLITAINE Pour les tarifs hors France Mtropolitaine, consultez notre site : www.ed-diamond.com
Tournez SVP pour dcouvrir toutes les offres dabonnement >>

55

Bon dabonnement dcouper et renvoyer ladresse ci-dessous

Voici mes coordonnes postales : Socit : Nom : Prnom : Adresse : Code Postal : Ville : Pays : Tlphone : e-mail :

dit par Les ditions Diamond Service des Abonnements B.P. 20142 - 67603 Slestat Cedex Tl. : + 33 (0) 3 67 10 00 20 Fax : + 33 (0) 3 67 10 00 21

Vos remarques :

En envoyant ce bon de commande, je reconnais avoir pris connaissance des conditions gnrales de vente des ditions Diamond ww w. g nsuivante ulinux m a g.com ladresse internet : www.ed-diamond.com/cgv et reconnais que ces conditions de vente me sont opposables.

Tournez SVP pour dcouvrir toutes les offres dabonnement

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

SySADmIn

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

A la dcouverte de Samba 4

par Julien Morot [Sysadmin passionn par les logiciels libres depuis 1998.]

En gestation depuis environ une dizaine dannes auprs de ses dveloppeurs, Samba 4 vise remplacer Samba 3, qui lui, assurait les fonctions dun domaine de type NT4. Rentrons au cur des rseaux Active Directory alors que la sortie dune version se profile lhorizon.

1 Introduction
La suite de logiciels Samba est une r-implmentation en logiciels libres des protocoles rseau clients et serveurs de Microsoft. La notion de libert est particulirement chre aux dveloppeurs du projet, car il a t le premier projet denvergure adopter cette licence en passant Samba 3.2 sous GPL v3 ds 2007. Jusquici, Samba3 tait capable de couvrir lensemble des fonctionnalits dun rseau de type NT4 avec un certain nombre damliorations, comme la possibilit dutiliser OpenLDAP comme backend de stockage ou encore un fonctionnement en cluster, bien que ces fonctionnalits soient relativement complexes mettre en uvre. Samba3 gre notamment lauthentification en mode serveur matre/esclave (PDC/ BDC pour Primary Domain Controler et Backup Domain Controler) et la fourniture des services de partage de fichiers et dimpression. La compatibilit avec lActive Directory de Microsoft est cependant limite la possibilit de joindre un domaine au sens domaine de scurit - et il devenait de plus en plus pressant de rattraper le retard accumul. En effet, Active Directory est sorti en 2000, Samba4 a t dmarr en 2003 et bien que la version finale commence pointer le bout de son nez, il aura fallu presque dix ans

pour achever le travail titanesque que reprsente la r-implmentation de tous les protocoles en jeu.

2 Quest-ce que lActive Directory?


LActive Directory consiste en une intgration particulirement pousse dun certain nombre de protocoles plus ou moins standardiss dans le but de fournir des services dauthentification, de configuration et dadministration (dploiement de logiciels et de configuration) centraliss. Fonctionnellement, cest une volution de ce quil tait dj possible de faire auparavant, car les principaux objets stocks dans lActive Directory sont des utilisateurs, des groupes et des ordinateurs. Techniquement, lvolution apporte par la migration vers de nouveaux protocoles, permet de partitionner les ressources de manire scurise, logique, le tout avec un passage lchelle plus important, car stock dans une base de donnes rplique, la NTDS pour NT Directory Services.

Le nom de domaine DNS est par dfaut utilis pour le nommage du domaine Active Directory. Par exemple, si votre domaine DNS interne est reseau.local, alors larborescence LDAP de lActive Directory sera DC=reseau,DC=local. Tout comme le DNS, il est possible de crer un ou plusieurs domaine(s) et sousdomaine(s) au sein de lAD. Lensemble des domaines et sous-domaines regroups au sein dune mme fort partagent le mme schma Active Directory (et donc LDAP), ainsi que des relations dapprobation entre les domaines. Par dfaut, la cration dun domaine ou dun sousdomaine entrane la cration dune relation dapprobation dauthentification transitive et bidirectionnelle. La fonctionnalit Catalogue Global au sein dun contrleur de domaine permet celui-ci de contenir une vue partielle des objets des autres domaines, afin de permettre la recherche dobjets situs dans dautres domaines plus rapidement sans ncessiter une rplication complte du contenu des diffrents domaines. Contrairement un rseau NT4/ Samba3, chaque contrleur de domaine est un contrleur de domaine matre, il ny a donc plus de notion de contrleur de domaine secondaire. A noter quavec Windows 2008 Server, Microsoft a introduit la notion de contrleur de domaine en lecture seule. Il assure lensemble des fonctions permises par un contrleur de domaine, lexception

2.1 Notion de domaine et de contrleur de domaine


Chaque serveur hbergeant lActive Directory ou une partition de celui-ci est appel un contrleur de domaine ou DC.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

43

SySADmIn

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

du fait quil est exclu de la rplication multi-matre et ne contient, comme son nom lindique, quune copie en lecture du domaine. Ce type de contrleur de domaine est en cours de prise en charge par lquipe Samba. Cependant, afin dassurer lunicit de certaines informations au sein du domaine ou de la fort, certaines fonctionnalits sont uniques: - Le rle dmulateur de Contrleur de Domaine Principal, unique au sein dun domaine, assure la compatibilit descendante pour lauthentification de type NT4. - Le rle Matre dIDentifiants Relatifs, unique au sein dun domaine, assure lunicit des identifiants allous aux autres contrleurs de domaine (lquivalent des UID/GID Unix). Relatif vient du fait que chaque objet est identifi par un identifiant unique (le SID), qui est la concatnation de lidentifiant de domaine et du RID de lobjet. - Le rle Matre dInfrastructure, assure la consistance des SID/GUID au sein des objets du domaine. En pratique, il gre surtout la consistance de la rsolution de nom des objets dans les groupes de lAD et le dplacement des objets entre domaines. - Le rle Matre de Schma, unique au sein dune fort. Gre la consistance et la rplication du schma au sein de la fort. - Le rle Matre de Nommage de Domaine, gre lunicit des noms de domaines AD lors de lajout ou la suppression de ceux-ci.

Ce port permet de requter en LDAP un contrleur de domaine pour des objets se situant sur lensemble de la fort. LActive Directory ayant pour but premier la gestion de lauthentification, des autorisations et du contrle daccs, les types dobjets principaux sont donc tout fait classiques dans ce type de configuration. On va donc retrouver: - Les units dorganisation, qui sont des conteneurs permettant de hirarchiser les autres objets que lon va retrouver. Elles sont utilises pour classer structurellement les objets en fonction de leur rle au sein dune organisation (services, sites, etc.), soit pour affecter des droits. Bien entendu, ces deux rles principaux ne sont pas mutuellement exclusifs. - Les comptes utilisateurs. - Les comptes dordinateur, permettant tout comme au niveau utilisateur dauditer et dauthentifier laccs aux ressources du domaine au niveau ordinateur. - Les groupes. Il existe trois tendues de groupes: locale, globale et universelle, permettant daffecter des autorisations respectivement pour uniquement le domaine local, tout domaine ou sous-domaine, ou toute la fort. Deux types de groupes existent, les groupes de scurit pour laffectation dautorisations et les groupes de distribution, qui servent surtout pour les applications de messagerie. Notez que contrairement aux groupes POSIX, lActive Directory prend en charge les groupes incluant dautres groupes.

3 Mise en place dun domaine sous Samba4


La maquette utilise pour cette mise en place se base sur une Debian testing. Ce choix est voulu pour simplifier cet article. Le DNS est un lment cl dune architecture Active Directory. Les clients notamment recherchent les contrleurs de domaine via des requtes DNS de type srv, afin de localiser un contrleur de domaine et un certain nombre de mises jour DNS dynamiques se font via Kerberos. Or, lquipe Samba a remont un certain nombre de patchs lquipe des dveloppeurs Bind pour une meilleure prise en charge de cette fonctionnalit, qui ncessite une version de Bind plus rcente que celle de la Debian stable. Afin de rester concentr sur la partie Samba, je nai prfr pas alourdir la mise en place du contrleur de domaine par la compilation de Bind en version 9.8 au minimum.

3.1 Prparation du serveur


Quelques paquets seront ncessaires, soit la compilation de Samba, soit son bon fonctionnement. On peut tous les installer en une fois de cette faon:
apt-get -y install build-essential libacl1-dev libattr1-dev \ libblkid-dev libgnutls-dev libreadline-dev python-dev \ python-dnspython gdb pkg-config libpopt-dev libldap2-dev \ bind9utils dnsutils libtool git xsltproc libpam0g-dev \ attr acl psmisc bind9 ntp libtalloc2 libtalloc-dev

2.2 Les types dobjets principaux


Les objets de lActive Directory sont stocks dans un annuaire compatible LDAP. Il est donc interrogeable naturellement via les ports LDAP (389/TCP), LDAPS (636/TCP), ainsi quun port spcial, le port catalogue global (3268/TCP).

Ensuite, le systme de fichiers et le montage de vos partitions doit prendre en charge les ACL et les attributs tendus. Il vous faudra donc modifier le fichier /etc/fstab en consquence. Exemple:
/dev/sda1 / ext3 user_xattr,acl,errors=remount-ro 0 1

44

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

A LA DCOUVeRTe De SAmbA 4

Pour viter de redmarrer le serveur pour les partitions actives, il est possible de les remonter avec les options adquates de cette faon:

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

mount -o remount,rw,acl,user_xattr /

Enfin, le protocole dauthentification par dfaut de lActive Directory tant Kerberos v5, il est important que les horloges soient lheure. Nous avons donc install le serveur NTPD lors des pr-requis. Il faut donc indiquer le serveur NTP source et le firewall du rseau devra autoriser les requtes NTP vers lextrieur. Cela revient dfinir le paramtre serveur du fichier /etc/ntpd.conf. Ce paramtre peut tre multivalu. Je vous recommande dutiliser fr.pool. ntp.org afin davoir une liste de serveurs sources fiables et disponibles. Petite note supplmentaire, en cas dutilisation dune autre distribution, il se peut que Avahi et son mcanisme de rsolution mdns soit prioritaire dans le mcanisme de rsolution de noms et que si, comme moi, vous utilisez un nom de domaine DNS avec .local comme suffixe, il faudra paramtrer le fichier /etc/nsswitch.conf de la sorte:
hosts: files dns

fichiers de configuration Bind, Kerberos, etc., correspondant au nom retenu pour le domaine. Par convention, jai cr un domaine avec un TLD .local. Le provisionning du domaine vous demandera le mot de passe du compte administrateur (dnomm administrator) et devra rpondre des exigences de complexit (chiffres, majuscules, minuscules et signes de ponctuation), sans quoi vous serez honor dune belle exception Python.
# provision Realm [DOMAIN.LOCAL]: Domain [DOMAIN]: Server Role (dc, member, standalone) [dc]: Administrator password: <secret!> Retype password: <secret !> Looking up IPv4 addresses Looking up IPv6 addresses No IPv6 address will be assigned Setting up share.ldb Setting up secrets.ldb Setting up the registry Setting up the privileges database Setting up idmap db Setting up SAM db Setting up sam.ldb partitions and settings Setting up sam.ldb rootDSE Pre-loading the Samba 4 and AD schema Adding DomainDN: DC=domain,DC=local Adding configuration container Setting up sam.ldb schema Setting up sam.ldb configuration data Setting up display specifiers Adding users container Modifying users container Adding computers container Modifying computers container Setting up sam.ldb data Setting up well known security principals Setting up sam.ldb users and groups Setting up self join Adding DNS accounts Creating CN=MicrosoftDNS,CN=System,DC=domain,DC=local Creating DomainDnsZones and ForestDnsZones partitions Populating DomainDnsZones and ForestDnsZones partitions See /usr/local/samba/private/named.conf for an example configuration include file for BIND and /usr/local/samba/private/named.txt for further documentation required for secure DNS updates Setting up sam.ldb rootDSE marking as synchronized Fixing provision GUIDs A Kerberos configuration suitable for Samba 4 has been generated at /usr/local/samba/private/krb5.conf Once the above files are installed, your Samba4 server will be ready to use Server Role: active directory domain controller Hostname: srv-dc1 NetBIOS Domain: DOMAIN DNS Domain: domain.local DOMAIN SID: S-1-5-21-2813939429-2675192644-3843174914 A phpLDAPadmin configuration file suitable for administering the Samba 4 LDAP server has been created in /usr/local/samba/private/ phpldapadmin-config.php.

3.2 Compilation et installation


Cet article se base sur la dernire version bta lors de sa rdaction, cest--dire la bta5. La compilation du logiciel revient faire un simple ./configure && make && make install habituel. Une seule dpendance est requise, ldb qui est une base de donnes avec une API proche de lAPI LDAP et qui sert de backend de stockage Samba. Je vous invite galement, pour plus de commodit, ajouter le chemin vers les binaires Samba au PATH de votre shell. Je supposerai dailleurs que cest le cas pour la suite, afin de simplifier les commandes.
wget ftp://ftp.samba.org/pub/ldb/ldb-1.1.9.tar.gz tar -zxvf ldb-1.1.9.tar.gz && cd ldb-1.1.6 ./configure && make && make install wget ftp://ftp.samba.org/pub/samba/samba4/samba-4.0.0beta5.tar.gz tar -zxvf samba-4.0.0beta5.tar.gz && cd samba-4.0.0beta5 ./configure && make && make install echo "export PATH=$PATH:/usr/local/samba/bin/:/usr/local/samba/ sbin/:" >> ~/.bashrc && source ~/.bashrc

3.3 Cration du domaine


La commande provision est lquivalent de la commande dcpromo.exe sur un DC Windows Server. Elle se charge de gnrer le domaine avec les comptes par dfaut et les

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

45

SySADmIn

3.4 Paramtrage du serveur DNS


Le stockage des donnes de la zone DNS domain.local tant ralis par Samba, la configuration de Bind est relativement simplifie. Dans un premier temps, on dfinit le stockage des zones devant passer par le plugin Bind-dlz (Dynamically Loadable : Zones) charger via le fichier /etc/bind/named.conf.local
include "/usr/local/samba/private/named.conf";

rdaction dun script dinit qui sera donc dune simplicit dconcertante, Debian fournissant en outre le modle de script /etc/init.d/skeleton.

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

3.6 Intgrer un poste au domaine


Pour intgrer un poste Windows un domaine AD, il faut obligatoirement une version professionnelle, les versions familiales ntant pas prises en charge. Que ce soit en IP fixe ou en DHCP, le poste client devra parvenir rsoudre votre zone DNS. Enfin, et ceci est une contrainte inhrente au protocole Kerberos, il ne doit pas y avoir un dcalage dhorloge de plus de cinq minutes entre le KDC et le client. Il ne reste plus qu intgrer les postes comme suit (ou bien graphiquement si a vous chante):
netdom /domain:domain.local /user:administrateur /password:secret MEMBER PC-JAMBON /joindomain

Puis, dans le fichier /etc/bind/named.conf.options, on indique le chemin vers la keytab. Une keytab est une cl Kerberos crypte et stocke sur disque, permettant dans ce cas prcis Bind de sauthentifier sur le KDC de faon transparente, sans ncessiter dentrer un mot de passe. Ce point est ncessaire, car la plupart des mises jour dynamiques des zones passent par TSIG-GSSAPI.
options { [...] tkey-gssapi-keytab "/usr/local/samba/private/dns.keytab"; }

3.7 Administration graphique


Le projet Samba tentant de reproduire au plus proche le comportement des diffrents composants de lActive Directory, les outils graphiques dits par Microsoft sont parfaitement fonctionnels et compatibles sur une infrastructure Samba. Il est donc galement possible de grer les stratgies de groupes depuis la console MMC approprie si elle est installe sur un poste Windows. La connexion au domaine devra tre effectue avec un compte disposant des droits admin du domaine. Sur un poste sous Windows XP, il faudra donc installer le kit de ressources techniques pour Windows 2003 Server SP1, ainsi que ladminpak. Les postes sous Windows Vista ou Windows Seven, quant eux, ncessiteront les Remote Server Administration Tools.

Cette cl devra bien entendu tre uniquement accessible par Bind, un chown root:bind /usr/local/samba/ private/dns.keytab, suivi dun chmod 0640 simpose donc. Pensez redmarrer le service bind pour que ces changements soient pris en compte. Notez quun serveur DNS, dont la vocation nest bien entendu pas de concurrencer Bind, est en dveloppement par lquipe Samba. La motivation est bien explique par le crateur de Samba, Andrew Trdigell, dans un post sur son blog qui va au-del du souci de simplification de linstallation. Le but est de permettre de rpondre facilement aux quatre mthodes de mise jour du DNS qui existent sur un rseau Active Directory, soit les mises jour DDNS signes via TSIG (Kerberos), les mises jour faites par les contrleurs de domaines en lecture seule via les MSRPC, les rplications de lAD inter-contrleurs de domaine via le DRS et enfin, les modifications ralises en LDAP, backend de stockage par dfaut. Pour les plus aventureux qui souhaiteraient tester, voici ce quil faut indiquer dans le fichier /usr/local/samba/ etc/smb.conf avant de relancer Samba:
server services = rpc, nbt, wrepl, ldap, cldap, kdc, drepl, winbind, ntp_signd, kcc, dnsupdate, s3fs, dns allow dns updates = True dns forwarder = 8.8.8.8 dns recursive queries = yes

3.8 Un second contrleur de domaine


Comme je le disais plus haut, un domaine Active Directory nest pas limit un contrleur de domaine, contrairement aux domaines Samba3/NT4. Autant donc profiter de cette possibilit pour assurer une redondance du systme dauthentification. Linstallation du second serveur se droule de faon similaire celle du premier. Je vous recommande donc galement une Debian testing, qui fournit les dpendances cites plus haut. La procdure de compilation et dinstallation est strictement similaire lorsque lon ajoute un contrleur de domaine un domaine existant. Cependant, il ne faudra pas lancer la commande provision, mais simplement dmarrer samba. Comme le serveur DNS est install dans un second temps, il faudra que le second serveur puisse rsoudre votre domaine AD via le DNS, en principe, en faisant pointer le fichier /etc/resolv.conf vers le premier contrleur de domaine.

3.5 Dmarrage et arrt


Pour dmarrer lensemble des processus, rien de plus simple, il suffit de lancer la commande samba. Pour larrter, un killall samba suffit. Je laisse donc au lecteur la

46

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

A LA DCOUVeRTe De SAmbA 4

On peut donc dsormais intgrer le domaine en tant que DC additionnel:


root@srv-dc2:~# samba-tool domain join domain.local DC -Uadministrator@domain.local --realm=DOMAIN.LOCAL Finding a writeable DC for domain domain.local Found DC srv-dc1.domain.local Password for [administrator@domain.local]: workgroup is DOMAIN realm is domain.local checking sAMAccountName Adding CN=SRV-DC2,OU=Domain Controllers,DC=domain,DC=local Adding CN=SRV-DC2,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=C onfiguration,DC=domain,DC=local Adding CN=NTDS Settings,CN=SRV-DC2,CN=Servers,CN=Default-First-SiteName,CN=Sites,CN=Configuration,DC=domain,DC=local Adding SPNs to CN=SRV-DC2,OU=Domain Controllers,DC=domain,DC=local Setting account password for SRV-DC2$ Enabling account Calling bare provision No IPv6 address will be assigned Provision OK for domain DN DC=domain,DC=local Starting replication Schema-DN[CN=Schema,CN=Configuration,DC=domain,DC=local] objects[402/1550] linked_values[0/0] Schema-DN[CN=Schema,CN=Configuration,DC=domain,DC=local] objects[804/1550] linked_values[0/0] Schema-DN[CN=Schema,CN=Configuration,DC=domain,DC=local] objects[1206/1550] linked_values[0/0] Schema-DN[CN=Schema,CN=Configuration,DC=domain,DC=local] objects[1550/1550] linked_values[0/0] Analyze and apply schema objects Partition[CN=Configuration,DC=domain,DC=local] objects[402/1614] linked_values[0/0] Partition[CN=Configuration,DC=domain,DC=local] objects[804/1614] linked_values[0/0] Partition[CN=Configuration,DC=domain,DC=local] objects[1206/1614] linked_values[0/0] Partition[CN=Configuration,DC=domain,DC=local] objects[1608/1614] linked_values[0/0] Partition[CN=Configuration,DC=domain,DC=local] objects[1614/1614] linked_values[28/0] Replicating critical objects from the base DN of the domain Partition[DC=domain,DC=local] objects[98/98] linked_values[23/0] Partition[DC=domain,DC=local] objects[307/209] linked_values[23/0] Partition[DC=DomainDnsZones,DC=domain,DC=local] objects[40/40] linked_values[0/0] Partition[DC=ForestDnsZones,DC=domain,DC=local] objects[18/18] linked_values[0/0] Committing SAM database Sending DsReplicateUpdateRefs for all the partitions Setting isSynchronized and dsServiceName Setting up secrets database Joined domain DOMAIN (SID S-1-5-21-2813939429-2675192644-3843174914) as a DC

cron rgulire qui ralisera un rsync rgulier de ce partage, aprs avoir pralablement mis en place un change de cls SSH:
*/5 * * * * root rsync -azvp --delete /usr/local/samba/var/locks/ sysvol root@srv-dc2:/usr/local/samba/var/locks/sysvol

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

3.9 Ajout dun serveur membre


Je ne reviendrai pas sur les tapes de prparation du serveur ni sur linstallation de Samba4, qui sont inchanges par rapport aux deux serveurs prcdents. Cependant, dans le but de cloisonner les services rseau, il peut tre utile de dlguer la gestion de certains services, comme le partage de fichiers, un serveur ddi:
root@srv-member:~# samba-tool domain join domain.local member -U administrator --realm=domain.local Password for [WORKGROUP\administrator]: Joined domain DOMAIN (S-1-5-21-2813939429-2675192644-3843174914)

A noter que depuis la bta4, il est permis de proprement promouvoir un serveur membre en contrleur de domaine sans perdre le SID du compte dordinateur de cette faon:
root@srv-member:~# samba-tool domain dcpromo domain.local DC -U administrator

Les services de partage de fichiers sont dsormais grs par un build des dmons Samba3 (nmpd et smbd) intgr Samba4. La littrature fleurit assez sur le sujet sur le net, de fait je ne my attarderai pas afin de rester cibl sur les relles nouveauts de Samba4.

4 Jouons un peu avec la ligne de commandes

4.1 samba-tool, le couteau suisse de ladministrateur

Il restera donc ensuite raliser le paramtrage de Bind de faon tout fait similaire au premier DC et adapter la rsolution du second serveur afin quil sinterroge lui-mme pour rsoudre les enregistrements du domaine. Veuillez noter un point cependant, le partage sysvol, qui contient les stratgies de groupe et les scripts de connexion appliqus sur les postes ou les utilisateurs du domaine, est rpliqu via un protocole, le DRS, dont limplmentation est encore jeune. Il faudra donc penser mettre en place une tche

Comme tout bon programme Unix, Samba4 est entirement administrable en ligne de commandes. La commande samba-tool permet de raliser lensemble des tches courantes dadministration dun rseau Microsoft Windows. La syntaxe de la commande est trs bien dtaille dans laide contextuelle. Les paramtres additionnels sont documents en indiquant le paramtre -H la sous-commande dsire sans indiquer de paramtre. Prenons connaissance du domaine que nous avons mis en place:
root@srv-dc1:~# samba-tool domain info 192.168.1.250 Forest : domain.local Domain : domain.local

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

47

SySADmIn

A LA DCOUVeRTe De SAmbA 4

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Netbios domain : DOMAIN DC name : srv-dc1.domain.local DC netbios name : SRV-DC1 Server site : Default-First-Site-Name Client site : Default-First-Site-Name root@srv-dc1:~# samba-tool domain level show Domain and forest function level for domain DC=domain,DC=local Forest function level: (Windows) 2003 Domain function level: (Windows) 2003 Lowest function level of a DC: (Windows) 2008 R2 root@srv-dc1:~# samba-tool fsmo show InfrastructureMasterRole owner: CN=NTDS Settings,CN=SRV-DC1,CN=Servers,CN=Default-First-Site-Name, CN=Sites,CN=Configuration,DC=domain,DC=local RidAllocationMasterRole owner: CN=NTDS Settings,CN=SRV-DC1,CN=Servers,CN=Default-First-Site-Name, CN=Sites,CN=Configuration,DC=domain,DC=local PdcEmulationMasterRole owner: CN=NTDS Settings,CN=SRV-DC1,CN=Servers,CN=Default-First-Site-Name, CN=Sites,CN=Configuration,DC=domain,DC=local DomainNamingMasterRole owner: CN=NTDS Settings,CN=SRV-DC1,CN=Servers,CN=Default-First-Site-Name, CN=Sites,CN=Configuration,DC=domain,DC=local SchemaMasterRole owner: CN=NTDS Settings,CN=SRV-DC1,CN=Servers,CN=Default-First-Site-Name,CN=Sites, CN=Configuration,DC=domain,DC=local

4.2 Sauvegarder Samba


Tout bon administrateur systme se pose bien videmment la question de la sauvegarde. La sauvegarde des donnes tant acquise, enfin je lespre, voyons comment sauvegarder la partie systme. La mise en place dun second contrleur de domaine, comme nous lavons fait, permet dj de sauvegarder lActive Directory en tant que tel. En cas de crash du systme ou de corruption des bases LDB de Samba4, il est donc possible de remonter lAD sur le serveur. Il reste nanmoins plus simple dans certains cas de ne raliser quune restauration de ce dont on a besoin. Dans les sources de Samba4, dans le rpertoire source4/ scripting/bin/ est prsent un script dj ralis nomm samba_backup. Jinvite par ailleurs le lecteur tre curieux et jeter un il aux diffrents scripts prsents dans ce rpertoire. Par dfaut, le script sauvegarde dans le rpertoire /usr/local/backups et conserve un historique de 90 jours. Le script sutilise de cette faon:
# ./samba_backup <rpertoire dinstallation> <rpertoire de sauvegarde>

Modifions la stratgie de scurit de mot de passe pour, par exemple, exiger 8 caractres (contre 7), mais nexiger quune modification de mot de passe annuelle (contre tous les 42 jours par dfaut):
root@srv-dc1:~# samba-tool domain passwordsettings set --min-pwd-length=7 --max-pwd-age=365 Minimum password length changed! Maximum password age changed! All changes applied successfully! root@srv-dc1:~# samba-tool domain passwordsettings show Password informations for domain DC=domain,DC=local Password complexity: on Store plaintext passwords: off Password history length: 24 Minimum password length: 7 Minimum password age (days): 1 Maximum password age (days): 365

Il restera donc planifier la tche via lhabituelle crontab et externaliser les sauvegardes sur un autre support.

Crons un groupe et ajoutons deux nouveaux utilisateurs ce groupe:


root@srv-dc1:~# samba-tool group add "Taverne de Moe" Added group Taverne de Moe root@srv-dc1:~# samba-tool user create h.simpson Spr1ngfi3l --given-name=Homer --surname=SIMPSON --must-change-at-next-login --company="Centrale Nuclaire" --script-path login.bat User h.simpson created successfully root@srv-dc1:~# samba-tool user create b.gumble Spr1ngfi3l --given-name=Barney --surname=GUMBLE --must-change-at-next-login --company="Duff" --script-path login.bat User b.gumble created successfully root@srv-dc1:~# samba-tool group addmembers "Taverne de Moe" h.simpson,b.gumble Added members to group Taverne de Moe root@srv-dc1:~# samba-tool group listmembers "Taverne de Moe" h.simpson b.gumble

Conclusion
Notre escapade la dcouverte du fonctionnement de lActive Directory et sa mise en place au travers de Samba4 sarrte l. Bien quil y ait encore beaucoup dire, nous avons pu voir dans quelle mesure le projet avait avanc de manire impressionnante et avoir un premier aperu de sa mise en place. Lquipe Samba nest pas encore prte lancer une mouture finale du logiciel, car des cueils subsistent encore et l, mais aprs tout, certains admins tmraires ont dj bascul en production des serveurs sur Samba4.

Comme vous le voyez, il est extrmement facile dautomatiser ladministration de son contrleur de domaine via la ligne de commandes. Jinvite le lecteur lancer la commande samba-tool sans paramtre pour prendre connaissance de ltendue des possibilits offertes (gestion des utilisateurs, groupes, sites, de la zone DNS, de la rplication, etc.).

48

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

SySADmIn

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Sauvegarde et clonage chaud de vos machines avec MondoRescue

par Benot Benedetti [Administrateur Systmes Linux, Universit de Nice Sophia Antipolis]

Vous connaissez srement dj des outils de clonage tels Clonezilla, ou de sauvegarde bass sur rsync. Dans le premier cas, loutil sexcute froid, machine teinte, en dmarrant sur un live CD, pour faire une image des disques au niveau bloc. Dans le second cas, la machine dont on dsire sauvegarder les fichiers est forcment allume, et la sauvegarde se fait au niveau systme de fichiers. Mondo Rescue offre lintrt de se placer entre ces deux mthodes.

1 Le projet
1.1 Prsentation
Mondo Rescue [MONDORESCUE] est une solution de sauvegarde sous GPL pour les systmes Linux et FreeBSD, ne de la frustration dHugo Rabson darriver sauvegarder des systmes Linux avec les solutions propritaires, peu flexibles, au dbut des annes 2000. Le projet est depuis maintenu par Bruno Cornec, contributeur des premires heures, qui a pris la tte de son dveloppement. Lintrt de MondoRescue tient du fait que vous navez pas stopper la machine pour en faire une image. Cela vite une coupure pour vos utilisateurs, et vous pouvez automatiser sa sauvegarde complte via une tche Cron. Mondo Rescue effectue son travail laide de trois commandes: mondoarchive, mondorestore et mindi. Les deux premiers sont, vous laurez devin, destins la sauvegarde et respectivement la restauration. Utilis par mondoarchive, mindi est quant lui

un utilitaire pour gnrer un mdia bootable. Ce mdia va contenir un Linux minimal, bas sur BusyBox. Pour soit dmarrer sur la machine sauvegarde lorigine, en cas de crash pour restauration, soit dmarrer une autre machine pour dployer limage. Il ressort donc que toutes les partitions dont vous voudrez sauvegarder les donnes devront tre montes, pour que Mondo Rescue puisse y accder. Mondo Rescue ne fonctionne que sous Linux, mais vous pourrez ainsi sauvegarder des partitions Windows montes. Prenez galement garde stopper tout service qui pourrait altrer les donnes pendant la sauvegarde (par MySQL) et corrompre celle-ci, par exemple en passant en runlevel 1, mode mono-utilisateur ddi la maintenance dune machine. Voici une liste non exhaustive de ses fonctionnalits: - support du RAID, LVM, ext2, ext3, ext4, FAT, VFAT, NTFS et de manire gnrale la plupart des systmes de fichiers supports par le kernel Linux ;

-n  ombreuses destinations et format de sauvegarde: locale, priphrique amovible, nfs, au format iso, sur priphrique bandes, directement vers un graveur CD/DVD ; -p  ossibilit de modifier la configuration de la machine de restauration: nouvelle table de partitions, nouveau systme de fichiers, migration vers du RAID et/ou LVM, ... ; -r  estauration du MBR, gestion de Grub, LILO ; -s  auvegarde complte ou diffrentielle ; -r  estauration partielle de certains fichiers ; -c  ompression gzip, bzip2 ou lzo ; -l es sauvegardes sont dans un format, compress ou non, lisible avec les outils Linux usuels ; -s  auvegarde des attributs et ACL SELinux.

1.2 Installation
Les diffrents paquets qui composent Mondo Rescue sont disponibles sur le serveur FTP du projet [FTP], pour de

50

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

SAUVeGARDe eT CLOnAGe CHAUD De VOS mACHIneS AVeC MOnDOReSCUe

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

nombreuses distributions, et leurs diffrentes versions. Cette large disponibilit est rendue possible grce un projet annexe de B. Corner, Project Builder [PROJECTBUILDER]. Pour trouver les paquets correspondant votre distribution, larborescence du serveur FTP est la suivante: ftp://ftp. mondorescue.org/<DISTRIBUTION>/<RELEASE NUMBER>. Pour nous simplifier la vie, chaque dossier de chaque distribution contient le fichier adquat ajouter la configuration de vos dpts, pour installer facilement le logiciel via votre gestionnaire de paquets habituel. Ainsi, sous Centos 6.3, qui sera notre distribution de rfrence dans cet article, le paramtrage des dpts se droule comme suit:
$ sudo wget ftp://ftp.mondorescue.org/rhel/6/x86_64/mondorescue.repo -O /etc/yum.repos.d/mondorescue.repo $ sudo yum clean all && yum makecache $ sudo yum -y install mondo

la question suivante, rpondez par laffirmative pour gnrer un ISO bootable contenant cette image, toujours dans /var/cache/mindi:
Shall I make a bootable CD image? (y/[n]) y Created bootable ISO image at /var/cache/mindi/mindi.iso

Vous pouvez aussi crer une cl USB bootable partir de cette image:
Shall I make a bootable USB device ? (y/[n]) y

Assurez-vous que la cl est bien branche, indiquez le priphrique /dev/sdX associ:


Please enter the device name of your USB device (e.g. /dev/sda) : / dev/sdb

Il vous sera demand si vous utilisez du RAID logique ou LVM. Dans la ngative, rpondez non aux deux questions. Linstallation est termine: il est clair que Mondo Rescue ne vous demandera pas normment defforts pour tre dploy sur les machines sauvegarder de votre parc.

Attention de ne pas vous tromper, le priphrique en question sera compltement cras, pour pouvoir le rendre bootable:
WARNING: This will erase Are you sure you want to Transforming /dev/sdb in lib/syslinux/mbr.bin) on all content on /dev/sdb use /dev/sdb (y/[n]) y a Bootable device ..Installing an MBR (/usr/ /dev/sdb

2.1 Mindi

2 Utilisation

Nous allons commencer par tester Mindi. Lutilisation directe de Mindi pour crer un mdia bootable nest pas ncessaire. Pour rappel, mindi est appel automatiquement par mondoarchive lors de la sauvegarde. Mindi va crer une image bootable contenant un noyau de boot bas sur la machine sauvegarde, un initrd avec des modules, et des outils issus de BusyBox utiles pour la restauration. Mieux vaut sassurer que ce support de boot est gnr correctement, car lutilisation de la sauvegarde serait limite voire compromise. Nous allons tester Mindi dans un cas simple: la cration dun CD bootable pour redmarrer la machine locale en cas durgence. Lancez mindi avec les privilges root:
$ sudo mindi Mindi Linux mini-distro generator v2.1.3-r3026

Redmarrez sur lUSB, limage mindi.iso (pour une VM) ou le CD grav partir de celle-ci. Vous devriez arriver sur un prompt, Tapez [Entre]. Si Mindi a travaill correctement, vous devriez arriver sur linvite de commande, et valider le bon fonctionnement de notre mdia de boot. Nous sommes dans une situation simple, o limage minimale gnre par la machine permet de dmarrer cette mme machine. Cette situation devrait convenir dans la plupart des cas dutilisation: clonage pour restauration dune mme machine (comme test ici), ou clonage dune machine pour re-dploiement de limage sur des machines identiques (comme linstallation dune salle de cours dont les postes ont une configuration matrielle quivalente). Dans dautres cas, il vous faudra prendre en compte les spcificits des machines source et de destination, et les diffrences potentielles de pilotes ncessaires au dmarrage. Vous avez la possibilit de modifier les fichiers de configuration /etc/mindi/* de Mindi pour lui indiquer tous les pilotes inclure. Cette situation ne devrait pas tre utile, la plupart des pilotes (rseau, disque) usuels tant contenus par dfaut dans limage cre par mindi.

Le programme vous demande quel kernel vous souhaitez utiliser pour gnrer limage. Laissez loption par dfaut, qui consiste se servir du kernel de la machine en cours dutilisation et rcuprer tous ses modules:
Do you want to use your own kernel to build the boot disk ([y]/n) ?

2.2 Sauvegarde
Pour dbuter, je vais prsenter la sauvegarde et la restauration avec Mondo Rescue dans un cas simple, o la machine a un volume de donnes faible. Il sera possible de sauvegarder les donnes au format iso sur un seul CD, et restaurer rapidement partir de celui-ci. Nous verrons plus loin un

Mindi va gnrer limage dans /var/cache/mindi:


In the directory /var/cache/mindi you will find the images:mindi-bootroot.40960.img

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

51

SySADmIn

scnario plus avanc avec nfs. Cela vous permettra dutiliser une petite machine virtuelle pour effectuer les manipulations suivantes, et faire connaissance avec Mondo Rescue.

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Pour effectuer votre sauvegarde, vous pouvez lancer


mondoarchive sans option. Une interface ncurse vous pr-

fichier /var/cache/mondo/difflevel.0 est cr, et contient un horodatage pour permettre une ventuelle sauvegarde diffrentielle future. Puis, mondoarchive excute Mindi pour crer limage bootable:
Calling MINDI to create boot+data disks ---evalcall---1--- Calling MINDI to create boot+data disk ---evalcall---2--- TASK: [*...................] 3% done; 0:32 to go

sentera diffrents crans pour prciser les options de votre sauvegarde. Utiliser mondoarchive en ligne de commandes permet nanmoins davoir accs toutes les options de sauvegarde:
$ sudo mondoarchive -OV -i -N -G -s 700m -p Centos -d /backup -S / tmp -T /tmp -I "/" -E "/var/cache/mondo"

Dans la commande prcdente, nous avons prcis les options suivantes: - -O: demande de crer une sauvegarde. - V : pour tester la sauvegarde gnre.
-i: sauvegarder au format ISO, dans un dossier local. - -N: ne pas sauvegarder les montages nfs, seulement les - dossiers locaux.

Ce boot+data disk indique que le support cr par Mindi contient limage minimale de boot, ainsi que des donnes. Ces donnes sauvegardes ne correspondent pas aux donnes que vous dsirez sauvegarder, indiques par loption -I. Elles correspondent des informations rcupres de la machine en cours de sauvegarde (configuration, liste des partitions et montage, ...) et des options passes mondoarchive. Toutes ces donnes faciliteront le processus de restauration. Attention, lors du travail de mindi, linactivit de la barre de progression peut vous donner limpression que mindi a plant. Ce nest pas le cas et pour vous assurer quil continue bien sa tche, jetez un il lactivit du fichier de log, depuis un autre terminal:
$ sudo tail -f /var/log/mondo/mindi.log

- G: utilisez gzip, plus rapide que bzip2, utilis par dfaut.


-s 700m: prcise la taille maximale dun ISO sauve- garder (4480M par dfaut, taille dun DVD).

- d /backup: destination de la sauvegarde (dans le cas dune sauvegarde locale /var/cache/mondo par dfaut). Assurez-vous davoir assez despace pour la totalit de vos donnes sauvegarder. - -p Centos : prfixe de la sauvegarde ISO. Le premier fichier de sauvegarde sappellera Centos-1.iso. Si la taille des donnes sauvegarder est suprieure la taille maximale dfinie, les suivants sappelleront Centos-2.iso, etc. (le prfixe vaut mondorescue comme valeur par dfaut).
-S /tmp: dossier temporaire dans lequel est cr le fi- chier ISO en cours, avant copie dans le rpertoire de destination final. Assurez-vous quil ait un espace libre minimal de la taille dun ISO gnrer.

Une fois mindi termin, mondoarchive reprend la main (le fichier journal de mondoarchive est /var/log/mondo/ mondoarchive.log) et commence la sauvegarde des fichiers, des plus petits aux plus gros:
---progress-form---1-----progress-form---4--0:00 to go ---progress-form---1-----progress-form---4--0:00 to go I am backing up your live filesystem now. TASK: [********************] 100% done; I am now backing up all large files. TASK: [*...................] 1% done;

/backup/Centos-1.iso, bootable, incluant limage boot+data de mindi . Un support bootable minimal /var/cache/ mindi/mondorescue.iso contenant le boot+data de mindi,

Notre sauvegarde est termine et contenue dans le fichier

- T /tmp: dossier pour contenir dautres fichiers temporaires durant lexcution de mondoarchive. - I "/": liste des chemins des dossiers sauvegarder, spars par un |, parcourus rcursivement ("/" par dfaut, pour faire une sauvegarde complte du systme. Aurait pu tre omis ici). - E: liste de dossiers ne pas sauvegarder. Quelle que soit sa valeur, mondoarchive ne sauvegarde pas /mnt/ floppy, /mnt/cdrom, /proc, /sys, /run ni /tmp. Lancez la commande prcdente, mondoarchive va commencer par crer une liste des fichiers sauvegarder. Par dfaut, une sauvegarde complte est dbute: paralllement, le

de quelques dizaines de Mo, sans aucune donne sauvegarde avec loption -I, est galement cr. Cela permet de bnficier dun support bootable supplmentaire pour dmarrer le processus de restauration.

2.3 Restauration partielle chaud


Mondo Rescue est une solution prvue pour faire des sauvegardes et restaurations compltes, mais peut tre utilise pour restaurer seulement une partie des fichiers sauvegards. Cette fonctionnalit est intressante, car elle peut tre utilise chaud sans redmarrer la machine: si la machine est toujours en ligne, fonctionnelle, il serait idiot de la redmarrer sur CD pour restaurer quelques fichiers. Plus particulirement pour nous ici, cela nous permettra galement

52

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

SAUVeGARDe eT CLOnAGe CHAUD De VOS mACHIneS AVeC MOnDOReSCUe

de vrifier notre sauvegarde. Lancez simplement mondorestore:


$ sudo mondorestore

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Une srie dcrans ncurse nous demande dabord dinsrer un ventuel mdia amovible contenant la sauvegarde. tant donn que celle-ci est dans un dossier local, cliquez OK , puis slectionnez Hard disks comme source de la sauvegarde (Figure 1), et indiquez le dossier contenant celle-ci, /backup, dans le troisime cran. Prcisez ensuite Centos comme prfixe de notre sauvegarde. La liste des fichiers va tre rcupre, et mondorestore va afficher un explorateur de fichiers (Figure 2). Cliquez sur [Entre] pour slectionner un fichier ou un dossier (son contenu) pour restauration (une toile indique les lments marqus comme restaurer). Utilisez les flches droite et gauche ou [TAB] pour naviguer vers le menu infrieur et au besoin tendre (menu More) ou rduire (menu Less) larborescence dun dossier, pour slectionner plus prcisment des lments contenus pour restauration. Ds que votre slection est faite, cliquez OK . mondorestore vous propose de spcifier dans quel rpertoire extraire les fichiers slectionns. / par dfaut, autrement dit leur chemin original. Prfrez, que ce soit dans notre exemple ou mme en situation relle, un dossier diffrent tel que /tmp, pour viter dcraser le fichier existant et pouvoir le comparer avec celui restaur. Cliquez OK . La restauration a eu lieu, simple, rapide et efficace, qui vous fait dj apprcier Mondo Rescue.

Figure 2

2.4 Restauration
Nous allons maintenant voir la restauration en dmarrant sur le live CD, bnficiant de plus de fonctionnalits et ncessaire en cas de crash srieux de la machine. Gravez le fichier Centos-1.iso gnr (ou montez-le sur une VM), et dmarrez votre machine dessus. Vous arrivez sur un prompt lilo, qui vous prsente les diffrents modes de restauration: nuke, interactive, compare ou expert. Notez que le clavier est en QWERTY avec Lilo. Tapez simplement [ENTREE], ce qui a pour effet de dmarrer le mode interactif par dfaut. Une fois dmarr, ce mode est tellement interactif quil vous affiche encore un menu vous prsentant les mmes options que LILO (Figure 3)! Slectionner Exit to shell est lquivalent du mode Expert: vous tes dans une console et pouvez excuter des commandes au besoin avant dinitier la restauration. Depuis la console (en mode expert ou aprs Exit to shell), lancez mondoestore sans argument pour r-afficher le menu de la figure 3.

Figure 3

Figure 1

Choisissez Compare Only! (quivalent au mode compare de lilo), pour comparer les fichiers prsents sur le disque avec ceux de la sauvegarde. Vous devez prciser o se trouve la sauvegarde. Choisissez CD-R, CD-RW ou DVD, tant donn que les fichiers sont contenus sur le disque avec lequel nous avons boot en live CD. Vous devez ensuite valider la table de partitionnement enregistre lors de la sauvegarde,

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

53

SySADmIn

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

pour que la comparaison puisse se faire. Ensuite, mondorestore charge les fichiers sauvegards et les compare avec les fichiers sur le disque, et vous affiche une liste des diffrences (Figure 4). Celle-ci devrait tre courte, nous venons deffectuer la sauvegarde. Une fois satisfait de la comparaison, cliquez Close. Vous revenez dans la console. Excutez mondorestore pour r-afficher le menu.

Figure 5

Un autre cran vous permet de modifier /etc/fstab, /etc/mtab ou la configuration de grub pour prendre en compte une ventuelle modification des partitions. Finalement, si vous utilisez des labels sur vos partitions, mondorestore vous permettra dexcuter e2label ou tune2fs pour que vos labels soient corrects avant de r edmarrer. Vous le voyez, le mode interactif permet vraiment de matriser tout le droulement du processus de restauration, et de vous rappeler et vous permettre deffectuer des oprations additionnelles pour ajuster le nouveau systme. Il reste que dans certains cas, des manipulations supplmentaires sont effectuer avant de commencer la restauration, non disponibles en mode interactif. Dans ce cas, il faut choisir le mode expert, pour passer en console, et excuter dventuelles commandes: configurer le rseau car les paramtres rseau rcuprs de la machine sauvegarde ne peuvent tre utiliss lors de la restauration, crer un RAID ou du LVM, etc. Une fois les modifications faites, lancez mondorestore pour r-afficher le menu, et lancez la restauration en mode automatique ou interactif. Vous pouvez accder aux informations rcupres par Mindi, dans la console en mode expert, situes dans le dossier tmp. Le fichier tmp/mondorestore.cfg contient par exemple tous les paramtres de la commande de sauvegarde et plus: compression, prfixe utilis, configuration rseau, etc.

Figure 4

Les menus Automatically (quivalent nuke depuis LILO) et Interactively (quivalent interactive) sont ceux vous permettant deffectuer la restauration, en suivant les mmes tches: partitionnement, formatage, copie de tous les fichiers sauvegards, excution de Grub, redmarrage. La diffrence est quen mode automatique, tout se passe sans votre intervention. Ce mode convient donc si vous souhaitez faire une restauration totale, avec les mmes paramtres qu la sauvegarde (les fameuses informations rcupres par Mindi). Le mode interactif convient pour les autres cas de restauration. Dans ce mode, avant chacune des tches listes prcdemment, un message de confirmation saffichera. Si vous ne souhaitez que restaurer certains fichiers, vous pouvez dcider de ne pas re-partitionner, ne pas formater, et/ou de ne pas restaurer lensemble des donnes. Un explorateur de fichiers similaire celui prsent dans la partie prcdente pour la restauration chaud vous permettra de slectionner seulement les fichiers dsirs (cf. Figure 2). Toujours dans ce mode, des crans de confirmation supplmentaires sont disponibles pour rpondre dautres scnarios de restauration. Ainsi, avant les tapes de formatage et partitionnement, un cran vous permet de modifier la table de partitionnement sauvegarde de la machine source (Figure 5), si vous changez la disposition de la machine cible (ajout dun disque, ajout ou suppression de partitions, etc.). Dautres messages vous donneront la possibilit de re-gnrer initrd, avec une commande telle que:
# cd /boot # mkinitrd -v -f initrd-`uname -r`.img `uname -r`

3 Pour aller plus loin


3.1 Destinations de sauvegarde
Nous navons vu que la sauvegarde et la restauration vers un dossier local, au format iso (option -i en ligne de commandes, et choix Hard Disk sous ncurse). Vous avez dautres destinations disposition. Vous pouvez slectionner un CD-R, CD-RW ou DVD comme support de sauvegarde

54

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

SAUVeGARDe eT CLOnAGe CHAUD De VOS mACHIneS...

(option -c, -w et -r respectivement). Pour un CD-RW, mondoarchive se chargera deffacer le CD-RW sil a dj t utilis.

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Loption -U sauvegarde vos donnes vers un priphrique USB. Pour un CD/DVD comme un priphrique USB, le support gnr sera bien sr rendu bootable. Il vous faudra galement prvoir lventualit de changer manuellement un support, si la taille des donnes sauvegarder est suprieure la taille dun support. Utilisez loption -t pour sauvegarder vers un support bandes magntiques. Dans tous ces cas de figure, vous devrez connatre le priphrique /dev/XXX concern (graveur de CD ou DVD, lecteur de bande ou cl/disque USB) et le renseigner mondoarchive avec loption -d. De plus, si votre volume de donnes sauvegarder est suprieur la taille dun support, vous devrez insrer un support supplmentaire ds que mondoarchive vous le demandera. Cest pourquoi la sauvegarde vers un dossier partag en NFS ou SSHFS est intressante: la souplesse du stockage de loption Hard Disk, et la centralisation de toutes vos sauvegardes en un point unique de votre rseau. Il vous faut pour cela utiliser loption -n. La sauvegarde est faite par dfaut au format ISO, donc toutes les options utilisables avec -i sont disponibles. Un dossier distant, pour pouvoir tre utilis, doit tre mont (prsent dans /etc/mtab) et/ou montable (prsent dans /etc/fstab). Par exemple, avec NFS, imaginons que nous ayons un serveur ladresse 192.168.0.10, exportant un dossier /backups. Ce dossier contient un rpertoire par serveur sauvegarder, du nom du serveur, pour organiser et retrouver facilement les sauvegardes. En ligne de commandes, pour sauvegarder un serveur de nom Centos-Server, cela nous donne:
$ sudo mondoarchive -O -N -G -2 -n nfs://192.168.0.10:/backups -d "Centos-Server" -T /tmp -S /tmp -E "/var/cache/mondo"

Nous navons pas prcis le prfixe (avec -p), le ou les diffrents fichiers iso auront donc le nom par dfaut mondorescue-1.iso, mondorescue-2.iso... Ils seront gnrs dans le dossier /backups/CentosServer du serveur NFS.

3.2 -i ou -n pour vos sauvegardes?


Vous vous demandez peut-tre lintrt dutiliser
-n, alors que vous pourriez monter le dossier distant

NFS ou SSHFS dans un dossier local, et faire votre

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

55

SySADmIn

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

sauvegarde au format ISO avec loption -i dans ce dossier local. Lintrt est dautomatiser la sauvegarde et la restauration au maximum. Comme indiqu prcdemment, la sauvegarde, Mindi sauve galement les paramtres de cette sauvegarde, quelles que soient les options utilises. Si vous faites une sauvegarde avec loption rpertoire distant, lorsque vous allez restaurer, les paramtres NFS/SSHFS de cette sauvegarde seront utiliss par dfaut. Que ce soit pour restaurer en mode interactif, les champs demands par loption Net Mount seront remplis automatiquement avec les paramtres de la sauvegarde. Ou encore en mode nuke/automatique, mondorestore montera automatiquement le bon dossier NFS depuis le serveur, pour rcuprer le(s) mdia(s) de sauvegarde.

chaque machine stockant ses sauvegardes dans un dossier son nom. Une sauvegarde complte est excute le lundi, une diffrentielle les autres jours:
#!/bin/bash DAY=`date +%A` NAME=`hostname` NFS_SERVER="192.168.0.10" NFS_SHARE="/backups" NFS_MOUNT="/mnt/backups" PREFIXE="full" DIFFERENTIELLE=""

3.3 Sauvegarde diffrentielle


Par dfaut, Mondo Rescue sauvegarde tous les fichiers des rpertoires qui lui sont demands. Il supporte galement les sauvegardes diffrentielles avec loption -D passe mondoarchive. Pour rappel, dans ce type de stratgie de sauvegarde, il y a une sauvegarde complte, les suivantes diffrentielles contiennent les fichiers modifis depuis cette sauvegarde. tout moment, une restauration ncessite au plus deux sauvegardes: la complte et la diffrentielle correspondant au jour dsir. Pour connatre les fichiers sauvegarder depuis la dernire sauvegarde complte, mondoarchive se base sur le temps au format epoch contenu dans le fichier /var/ cache/mondo/difflevel.0. Tout fichier postrieur cette date est sauvegard. Une sauvegarde diffrentielle avec mondoarchive ne se base donc absolument pas sur lexistence ou non dune sauvegarde complte, ou son contenu, mais sur ce fichier difflevel.0. vous de vous assurer que vous avez bien une sauvegarde complte, et de changer de prfixe pour ne pas craser une complte par lexcution dune diffrentielle. Avec loption -D, si un tel fichier difflevel.0 nexiste pas, une sauvegarde complte est automatiquement effectue... mais ne cre pas de fichier /var/cache/mondo/difflevel.0! Il vous faut donc obligatoirement excuter mondoarchive sans loption -D, pour gnrer un tel fichier par une sauvegarde complte explicitement demande.

if [ $DAY != "lundi" ]; then PREFIXE="diff-${DAY}" DIFFERENTIELLE="-D" fi mount -t nfs ${NFS_SERVER}:${NFS_SHARE} ${NFS_MOUNT} service mysqld stop #sauvegarde mondoarchive -O ${DIFFERENTIELLE} -N -G -2 -n nfs://${NFS_ SERVER}:${NFS_SHARE} -p ${PREFIXE} -d "${NAME}" -T /tmp -S /tmp -E "/var/cache/mondo" service mysqld start #On rcupre au passage le mdia bootable minimal mv /var/cache/mindi/mondorescue.iso ${NFS_MOUNT}/${NAME} umount ${NFS_MOUNT}

Pour quil soit excut tous les jours, sauvegardez ce script dans /etc/crond.daily/mondoarchive et donnez-lui les droits dexcution:
$ sudo chmod u+rwx,go-rwx /etc/cron.daily/mondoarchive

Le script et la stratgie de sauvegarde sont basiques, avec une possibilit de restauration des donnes datant seulement dau plus une semaine. Mais cela vous dmontre quen ajustant cet exemple, vous pouvez bnficier dune solution de clonage chaud automatise rapidement avec Mondo Rescue. Soyez conscient galement que lexcution sous cron de mondoarchive ne permet pas de lutiliser de manire interactive: si vous sauvegardez vers un support qui peut ncessiter un changement manuel (insrer une nouvelle cassette par exemple), a ne fonctionnera pas. La documentation officielle de Mondo Rescue propose une partie pour vous aider mettre en place une tche cron interactive laide de at et screen [BACKUPCRON].

3.4 Automatiser tout a


Maintenant que nous connaissons un peu plus Mondo Rescue, pourquoi ne pas coupler sa capacit sauvegarder chaud avec une tche cron, pour automatiser la sauvegarde complte dune machine? Nous allons crire un script shell pour vous servir de base de sauvegarde. Les sauvegardes seront stockes de manire similaire celle voque prcdemment, sur un serveur NFS,

3.5 Restauration en PXE


Dans le cas dune sauvegarde au format ISO, vous pouvez utiliser une installation PXE pour dmarrer sur le rseau une machine restaurer. Les sauvegardes doivent tre mises disposition sur un serveur NFS, pour que la

56

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

SAUVeGARDe eT CLOnAGe CHAUD De VOS mACHIneS AVeC MOnDOReSCUe

machine dmarre puisse y accder en NFS. La sauvegarde peut avoir eu lieu avec loption -i ou -n en SSHFS, mais la restauration, comme expliqu prcdemment, sera plus simple si la sauvegarde a t faite directement en NFS avec loption -n.

Conclusion
Mondo Rescue est un projet mature et stable, dont on nentend pas assez parler, mon avis. Il est vrai que comme outil de clonage, il ne peut rivaliser avec des projets ddis plus pousss comme CloneZilla, qui peuvent travailler en Multicast. Mais son norme avantage est de travailler chaud. ma connaissance, il ne connat pas dalternative et mrite de vous y intresser quelle que soit la taille de votre parc, ne serait-ce que pour faire des sauvegardes et restauration sans PXE. Si vous tes une petite structure, il pourra aussi largement faire office de solution de clonage et de dploiement dimages. Vous trouverez galement sur la documentation officielle un processus dtaill pour faire de la virtualisation de serveurs physiques [P2V]. noter que Mondo Rescue offre une intgration et des fonctionnalits pousses sur les serveurs HP Proliant, le responsable du projet tant employ et spcialiste open source chez HP. En particulier, la restauration via Mondo Rescue sintgre avec la technologie iLO [iLO] de HP. Dans tous les cas, Mondo Rescue est facile mettre en place, vous sauvera la mise et vous vitera bien des regrets lors de plantage.

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Il vous faut dj disposer dune installation PXE. Ce nest pas le sujet de larticle, vous pourrez trouver facilement des informations rcentes sur Internet pour Centos 6 [PXE]. Une fois en place, rcuprez les fichiers initrd.img et vmlinuz depuis le premier ISO de la sauvegarde, ou depuis le mdia bootable minimal /var/cache/mindi/mondorescue.iso, gnrs par mondoarchive:
$ $ $ $ sudo sudo sudo sudo mount /backups/centos6/Centos-1.iso /mnt/cdrom -o loop cp /mnt/cdrom/initrd.img /tftpboot/ cp /mnt/cdrom/vmlinuz /tftpboot/ umount /mnt/cdrom/

Les fichiers nont pas faire partie de la sauvegarde que vous souhaitez restaurer. Crez ensuite le fichier /tftpboot/pxelinux.cfg/default:
LABEL Centos-Server MENU LABEL Centos-Server kernel vmlinuz append initrd=initrd.img load_ramdisk=1 prompt_ramdisk=0 ramdisk_size=131072 selinux=0 rw root=/dev/ram iso acpi=off apm=off devfs=nomount exec-shield=0 pxe

Dmarrez la machine restaurer sur le rseau, elle va charger en mmoire les fichiers ncessaires en TFTP, pour finalement vous prsenter le menu interactif de mondorestore, pour comparer les fichiers, ou lancer la restauration automatique ou interactive depuis les sauvegardes du serveur NFS. Ce cas de restauration simple fonctionne dans le cas o la machine sauvegarde la t en NFS, et la restauration se passe sur celle-ci. Pour vos autres machines qui seraient dans le mme cas, vous pouvez procder de mme, en rcuprant les fichiers respectifs initrd.img et vmlinuz dans /tftpboot (en leur donnant un autre nom ou en crant des rpertoires par machine bien sr), et crer une entre dans pxelinux.cfg. part que la restauration peut avoir lieu sur une machine dont la configuration diffre de la machine sauvegarde, ou la sauvegarde na pas t faite avec loption -n de NFS, ou les paramtres du serveur NFS hbergeant les sauvegardes utiles au PXE ne sont pas les mmes que celui du serveur NFS ayant servi la sauvegarde. Dans tous ces cas, les fameux paramtres sauvs par Mindi lors de la sauvegarde, contenus et visibles dans tmp depuis le mode expert, utiliss pour restaurer la machine, ne sont pas bons. Il va falloir prciser les bons paramtres dans le menu de PXE. Les diffrents paramtres utilisables dans le menu sont prsents dans /usr/share/doc/mindi-2.1.3/README.pxe. Dans notre exemple, pour prendre en compte une nouvelle configuration ip de la machine restaurer et NFS du serveur de stockage des sauvegardes:
LABEL Centos-Server MENU LABEL Centos-Server kernel vmlinuz append initrd=initrd.img load_ramdisk=1 prompt_ramdisk=0 ramdisk_size=131072 selinux=0 rw root=/dev/ram iso acpi=off apm=off devfs=nomount exec-shield=0 pxe ipconf=eth0:dhcp netfsmount=192.168.100.10:/backup-images netfspath=centos6-server

Rfrences
[MONDORESCUE] http://www.mondorescue.org [FTP] ftp://ftp.mondorescue.org/ [PROJECTBUILDER] http://projectbuilder.org/ [BACKUPCRON] http://www.mondorescue.org/docs/mondorescue-howto. html#BACKUP-CRON [PXE] http://www.thenoccave.com/ 2012/03/28/centos-6-pxe-server/ [P2V] http://www.mondorescue.org/ docs/p2v.pdf [iLO] http://h18013.www1.hp.com/ products/servers/management/ remotemgmt.html

Grce ces options, vous pouvez juste utiliser un unique couple de fichiers initrd.img/vmlinuz pour dmarrer en PXE, et paramtrer les entres des menus de chaque machine au besoin.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

57

NeTADmIn

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Testez vos applications web avec JMeter

par Jrmy Hage [Ingnieur Systmes et Rseaux Oxalide]

la fin du dveloppement dun site internet, il est toujours intressant voire essentiel de tester son application avant sa mise en production en lui faisant subir un test de charge afin dvaluer ses performances. Pour ce faire, je vous propose de dcouvrir JMeter, un outil permettant deffectuer ce type de tests.
un des critres les plus importants pour quun site soit apprci de ses visiteurs est que son chargement soit performant. En effet, bien que le plus important sur un site web soit le contenu quil propose, les internautes sont gnralement vite lasss par les ventuelles lenteurs quils peuvent rencontrer. Pour ne pas avoir de mauvaises surprises, et ne pas risquer de perdre des visiteurs, il est important de savoir si larchitecture ddie votre site est adapte aux exigences de votre application en matire de consommation des ressources en situation de fort trafic. Un test de charge vous permettra donc davoir une estimation du nombre de requtes par seconde que votre infrastructure pourra supporter et davoir une ide du nombre de visiteurs simultans que votre site pourra accueillir. Bien quils puissent tre utiliss tout moment, ces tests sont gnralement effectus avant la mise en production dun site ou dune nouvelle version dun site, ou encore avant de grands vnements tels que les soldes pour les sites marchands, les grands championnats pour les sites de sport, les lections pour les sites dinfo, etc. Les rsultats de ces tests permettent danticiper dventuels problmes de charge des serveurs et ainsi dajuster les ressources matrielles au trafic attendu. Ils peuvent galement mettre en avant les possibles faiblesses

de lapplication teste et orienter les recherches doptimisation. Aprs une prsentation de JMeter, nous verrons la faon de crer un scnario et lexcuter. Nous verrons ensuite comment exploiter et interprter les rsultats que vous obtiendrez.

Son utilisation consiste dans un premier temps tablir un scnario de test, cest--dire un exemple de session de navigation dun visiteur, puis faire rpter ce scnario autant de fois et par autant de visiteurs (ou threads) simultans que vous laurez dcid. La figure 1 reprsente de manire gnrale le fonctionnement de JMeter. Le contrleur est la machine partir de laquelle vous avez cr votre scnario. Cette instance vous permettra galement de contrler les injecteurs qui eux se chargent dexcuter le scnario. Lorsque vous fournissez un scnario plusieurs injecteurs la fois, le mme scnario est excut par chacun dentre eux, cest--dire quil ny a pas de rpartition du nombre de threads entre les 2 instances.

1 Prsentation de JMeter
JMeter est un logiciel permettant deffectuer des tests de charge de plusieurs services diffrents (ftp, mail, ldap, ...), mais nous nous concentrerons ici sur la mise en uvre dun test de charge dune application web. JMeter est crit en Java et son dveloppement est gr par la fondation Apache.

Illustration 1: Fonctionnement global de JMeter

58

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

TeSTeZ VOS APPLICATIOnS Web AVeC JMeTeR

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Ce schma reprsente le cas idal o vous possderiez des ressources matrielles disponibles. Seulement ce nest pas toujours le cas et on pourrait plus simplement se contenter dune seule instance de JMeter partir de laquelle vous laborerez le scnario et lancerez le test de charge. Cependant, il faut noter que lors dun test, la charge gnre par JMeter nest pas ngligeable, donc plus linfrastructure de votre site est robuste et plus vous aurez besoin dinjecteurs et de bande passante afin de pousser vos tests le plus loin possible. Les rsultats obtenus sur JMeter sont reprsentatifs de ce que lon obtiendra ct client mais ne vous permettront pas de dterminer clairement quelles ressources arrivent saturation lors de la monte en charge. Cest pourquoi il est important pour lanalyse de vos rsultats davoir des graphes de comportement de vos serveurs. Il serait intressant davoir au moins les informations portant sur le load average, la consommation mmoire et la bande passante. Dans le cas de ce test, jai utilis Cacti qui est un outil simple permettant dobtenir ces informations.

que lon y rflchisse srieusement afin que les rsultats obtenus collent le plus la ralit. Lapplication de test que jutiliserai dans cet article est un Dotclear hberg sur un petit serveur physique possdant 2 CPU dual core, 2Go de mmoire vive et 1Go de bande passante. Jai fait le choix de tester un blog car les scnarios possibles ne sont pas vraiment nombreux, donc un seul test nous permettra davoir des rsultats significatifs. Comme il sagit dun test dun site nexistant que pour cet article, je nai pas rellement dobjectifs. Je me contenterai donc de fixer le nombre de threads simultans assez haut pour atteindre le seuil critique et me faire une ide de sa valeur. Le scnario que lon utilisera se divise en fait en 2 parties: 1-C  onsultation de 2 articles (200 threads simultans maximum) - Linternaute arrive sur la page daccueil et y reste 10 secondes. - Il clique sur le premier article et le lit durant 30 secondes. - Il retourne sur la page daccueil durant 5 secondes. - Il clique sur le deuxime article et le lit durant 30 secondes. - Il recommence. 2-C  onsultation dun article et dpt dun commentaire (50 threads maximum) - Linternaute arrive sur la page daccueil et y reste 10 secondes. - Il clique sur le premier article, le lit et rdige un commentaire en 50 secondes. - I l attend une minute et recommence. La division en deux parties est ncessaire car la frquence des deux scnarios nest pas identique puisque la consultation darticle est gnralement plus frquente que le dpt dun commentaire.

Lexcution du scnario se fera de manire progressive, cest--dire que nous augmenterons le nombre de threads de manire priodique jusqu atteindre la limite spcifie par notre configuration. Il est important de ne pas monter trop vite en charge afin que nous puissions visualiser la manire dont ragit notre infrastructure. Notre test stalera donc sur un peu plus de 8 heures.

3 Installation et utilisation de JMeter


3.1 Installation
JMeter est prsent dans les dpts de la plupart des distributions, mais dans cet article, jutiliserai la dernire version rcupre depuis le site de JMeter (http:// jmeter.apache.org/download_jmeter.cgi). Il sagit de la version 2.7. Linstallation est trs simple, il suffit de tlcharger larchive, la dcompresser et lancer lexcutable jmeter qui se trouve dans le rpertoire bin de larchive. JMeter tant un programme Java, il faut installer le JRE pralablement. Le graphage des rsultats nest pas vraiment le point fort de JMeter. Par dfaut, ils ne sont pas trs lisibles. Heureusement, il existe un plugin qui gre trs bien cela. Vous pouvez le tlcharger cette adresse : http://code.google. com/p/jmeter-plugins/. Pour linstaller, il suffit de copier le fichier JmeterPlugins.jar dans le rpertoire lib/ext du rpertoire dinstallation de JMeter.

2 Avant de commencer
Il est essentiel davoir un objectif avant de commencer un test afin de savoir si votre infrastructure est dimensionne selon vos attentes de trafic. Cest pourquoi vous devez vous poser les questions suivantes: - Quel est le nombre moyen de visiteurs simultans attendus: - Lors dun trafic normal? - Lors dun pic de trafic? - Quel scnario de navigation sera le plus reprsentatif dune visite standard? Le choix du scnario est essentiel dans les tests de charge et il mrite

3.2 Prsentation de linterface


Bien que JMeter nous offre un bel environnement graphique, son utilisation nest pas trs intuitive. La configuration dun scnario passe par celle de diffrents lments plus ou moins indpendants que vous pouvez ajouter selon vos besoins. Commenons par une prsentation de lcran daccueil de JMeter:

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

59

NeTADmIn

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

cran daccueil de JMeter

Lencadr rouge reprsente les raccourcis des menus. Vous pourrez partir de l lancer vos tests, les stopper ou encore les rinitialiser. Lencadr orange est la partie o seront lists les diffrents lments du test. Nous verrons par la suite quelques-uns des lments les plus utiliss dans les tests de performance web. Enfin, cest dans lencadr vert que seffectuera la configuration des lments slectionns dans la partie orange.

On peut dj voir que nous avons 2 parties principales: le plan de test et le plan de travail. Le plan de test contiendra toutes les informations ncessaires au test de charge, cest--dire les lments de configuration du nombre de threads, la gestion des requtes ou encore des cookies. Quant au plan de travail, il contiendra tous les lments hors test et tout ce que vous souhaitez conserver temporairement. Cette partie nest pas sauvegarde lenregistrement dun scnario. Le groupe dunits est llment obligatoire pour tout test de charge avec JMeter. Nous en avons 2 dans notre exemple: Consultation et Commentaire. Ils reprsentent les 2 parties du scnario que nous avons vu plus haut. Cet lment permet de: - fixer le nombre de threads simultans. - la dure de monte en charge, cest--dire le temps que devra mettre JMeter pour lancer tous les threads. - le nombre ditrations, cest--dire le nombre de fois que le scnario devra tre rpt par chaque thread. Il est possible deffectuer une rptition infinie. Dans ce cas, je vous conseille de cliquer sur Programmateur de dmarrage afin de configurer la dure du test.

3.3 laboration du scnario


Nous pouvons commencer ajouter des lments. Pour un test de charge de site web, les lments visibles ci-dessous sont suffisants pour crer un scnario, grer le nombre de threads simultans et visualiser les rsultats du test.

Arbre de configuration du test

test,

Le groupe dunits sobtient en cliquant droit sur Plan de puisAjouter -> Moteurs dutilisateurs -> Groupe dunits.

60

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

TeSTeZ VOS APPLICATIOnS Web AVeC JMeTeR

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Llment Paramtres HTTP par dfaut vous permettra de fournir au groupe dunits des paramtres HTTP tels que le nom de domaine du site (ou son IP), le port utiliser, etc. Pour ajouter cet lment, il faut cliquer droit sur Groupe dunits puis : Ajouter -> Configurations -> Paramtres HTTP par dfaut . Le gestionnaire de cookies nest rellement important que pour les sites utilisant des cookies ou des sessions gres par des cookies. Pour ajouter cet lment, il faut cliquer droit sur Plan de test puis: Ajouter -> Configurations -> Gestionnaire de cookie HTTP. Il pourrait tre intressant pour la configuration de cet lment de cocher Nettoyer les cookies chaque itrations ? afin que lors de la rptition dun scnario par un mme thread, le cookie soit gnr nouveau. Un contrleur est llment qui vous permettra de grer un groupe de requtes HTTP. Il existe une quinzaine de types de contrleurs diffrents. Ces lments permettent de spcifier comment seront gres les requtes dun groupe. Le scnario que nous prsenterons ici tant assez simple, nous nous contenterons dun contrleur simple. Pour lajouter, il faut cliquer droit sur Groupe dunits puis: Ajouter -> Contrleurs Logiques -> Contrleur Simple. Llment Serveur Proxy HTTP nous permettra denregistrer un scnario simplement en naviguant sur les pages que nous voulons y inclure. Pour ajouter cet lment, il faut cliquer droit sur Plan de travail puis: Ajouter -> lments Hors Test -> Serveur Proxy HTTP. Le principe est que JMeter deviendra notre proxy le temps de lenregistrement du scnario. Ainsi, il pourra enregistrer toutes les requtes que nous faisons. Pour ce faire, il faut dans un premier temps configurer votre navigateur afin quil utilise le proxy local coutant sur le port 8080. Ensuite, au niveau de JMeter, il faut slectionner llment Serveur Proxy HTTP puis choisir le contrleur dans lequel senregistrera la liste de requtes. Vous pouvez exclure des URL ou des types de fichiers en spcifiant les motifs dans le champ Motifs exclure . De manire gnrale, il nest pas trs utile de conserver tout le contenu statique, sauf si vous souhaitez tester votre bande passante. En effet, la charge gnre par les requtes dlments statiques est ngligeable face celle gnre par PHP ou autres langages de script. Enfin, il faut cliquer sur Lancer. Vous pouvez maintenant naviguer dans votre site en suivant le scnario que vous avez tabli pralablement. Pour terminer, vous appuyez sur Arrter. Noubliez pas de restaurer la configuration de votre navigateur dans son tat dorigine.

Si vous droulez le contrleur slectionn, vous pourrez voir la liste de toutes les requtes effectues lors de votre navigation. Comme la visite dun site est ponctue par des temps de lecture du contenu des pages, il faut ajouter des compteur de temps afin de marquer des pauses aprs chaque page, comme nous lavons vu dans la prsentation du scnario. Il existe une dizaine de compteurs de temps. Nous allons utiliser un compteur de temps fixe. Pour lajouter, il faut cliquer sur la requte concerne puis Ajouter -> Compteur de temps -> Compteur de temps fixe. Sa configuration est simple, il suffit de spcifier le nombre de millisecondes patienter. Tous les lments permettant de faire le test ont t ajouts. Il faut maintenant ajouter llment qui nous permettra denregistrer les rsultats obtenus dans un fichier que nous pourrons exploiter aprs le test. Pour ce faire, nous allons ajouter un des lments du plugin que nous avons install en cliquant droit sur Plan de test: Ajouter -> Recepteur -> jp@gc - Response Codes per Second. Il faut noter que durant les tests de charge, JMeter est assez gourmand en ressources, surtout lorsquil doit afficher les rsultats en temps rel. Je vous conseille donc de toujours

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

61

NeTADmIn

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

lancer vos tests en ligne de commandes. Vous pourrez exploiter les rsultats obtenus aprs le test. Pour ce faire, il faut spcifier le fichier dans lequel vous enregistrerez vos rsultats. Un seul rcepteur est ncessaire pour recueillir les rsultats, mais plusieurs pourront tre utiliss pour les visionner une fois que le test sera fini. Pour cela, il faut juste spcifier le chemin du fichier dans le champ Nom du fichier. Lorsque le test sera fini, nous ouvrirons ce mme fichier en cliquant sur Parcourir et le graphe sera gnr. Si vous cliquez sur Configurer, vous pourrez slectionner ce qui sera enregistr dans le fichier. Pour ce test, je nai eu ajouter que Nombre dunits active en plus de la slection par dfaut. Cette option permettra dobtenir des graphes de temps de rponse en fonction du nombre de threads actifs. Pour faire ce test, jai utilis 2 instances Jmeter: un contrleur et un injecteur. Je ne mattarderai pas sur la configuration dun test en utilisant un injecteur, la procdure nest pas trs complique et est bien explique sur le site du projet JMeter. Nous pouvons enfin enregistrer notre plan de test et entrer la commande suivante pour lancer le test:
./jmeter -n -X -t /chemin/vers/fichier.jmx

4.1 Les graphes JMeter


Tout dabord, voici le graphe du nombre de rponses obtenues par seconde: On remarque que lon atteint vers 23h40 un seuil de 10 requtes par seconde. Si nous jetons un il au dtail du temps de rponse moyen, on retrouve le phnomne. peu prs au mme moment, vers 23h00, le temps de rponse des requtes subit une forte augmentation :

Nombre de rponses par seconde (code 200)

4 Exploitation des rsultats


Une fois le test termin, on peut visualiser les rsultats obtenus en lanant JMeter et en ajoutant les diffrents rcepteurs que lon souhaite. Les rcepteurs que jutilise le plus souvent sont: - jp@gc - Response Codes per Second ; - jp@gc - Response Times Over Time ; - jp@gc - Response Times vs Threads ; - jp@gc - Active Threads Over Time ; Vous trouverez ci-dessous les rsultats obtenus pour ce test.

Temps de rponse en fonction du temps

En regardant le graphe de load average du serveur obtenu grce Cacti, on peut voir que les 4 de load sont franchis vers 23h galement, et comme nous avons 4 curs, cela indique un dbut de surcharge.

Load Average durant les 6 premires heures

62

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

TeSTeZ VOS APPLICATIOnS Web AVeC JMeTeR

Ainsi, pour dterminer une approximation du nombre de visiteurs simultans que peut accueillir notre plateforme, il suffit de regarder sur la figure 7 le nombre de threads actifs entre 22h40 et 23h40:

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

On peut galement conclure que cest la ressource CPU qui est sature et qui empche dobtenir des rsultats plus levs puisque les CPU ont atteint les 100 % dutilisation et le load average a t lev pendant le test alors que la RAM nest pas entirement consomme.

Conclusion
Nous venons donc de voir un test de charge qui, bien quil soit simple, constitue une bonne base pour vos prochains tests.
Nombre de thread actifs en fonction du temps

Donc pour conclure, notre serveur pourrait accueillir entre 170 et 200 internautes simultanment sans quils ne subissent de lenteur de chargement sur le blog. En effet, daprs le graphe des temps de rponse en fonction du nombre de threads, on peut voir que pour la tranche 170-200 threads, le temps de rponse moyen ne dpasse pas 1 seconde.

On aurait pu tendre lutilisation de Jmeter des tests de composants logiciels. En effet, on aurait pu samuser tester notre application sur diffrents serveurs web en refaisant le match Apache vs Nginx vs LightHTTPd pour voir lequel est le plus performant. On aurait galement pu ajouter un reverse proxy afin de voir combien de requtes par seconde supplmentaire notre serveur pourrait supporter. Les testeurs de charge sont donc les outils idaux pour justifier le choix dun composant par rapport un autre si la performance est lun des critres de dcision.

Temps de rponse en fonction du nombre de threads

Graphe de consommation de la RAM

Consommation CPU

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

63

MObILIT

la dcouverte dAndroid :
Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Le systme graphique

par Benjamin Zores [Architecte Android et Linux Embarqu @ Alcatel-Lucent]

Nous nous sommes arrts lors du prcdent chapitre de cette srie au mcanisme dinitialisation du systme, avec une carte qui effectuait un premier dmarrage. Place maintenant la comprhension dun composant cl de tout systme embarqu moderne avec la gestion de laffichage graphique.
our rappel, notre prcdente exprimentation se basait sur une carte PandaBoard base de processeur OMAP4 de TI. Cette dernire, nativement supporte par Android 4.0, supporte bien videmment un grand nombre de fonctionnalits, dont la gestion native de l'affichage. Le noyau fourni par Google pour cette carte sarrte cependant la gestion d'un cran numrique via connectique HDMI. C'est intressant, certes, mais pas forcment adapt notre besoin. Nous souhaiterions plutt utiliser un cran LCD avec une dalle tactile afin d'utiliser notre priphrique comme une tablette ou un smartphone en lieu et place d'une TV. C'est videmment l que commencent les problmes. Voyons donc comment rpondre ce besoin. Avant donc mme de rentrer dans les mandres d'Android et l'architecture logicielle de son sous-systme graphique, c'est au niveau le plus bas, et le plus gnrique, savoir le noyau Linux, qu'il va falloir intgrer notre cran.

Fig.1: Architecture interne dun contrleur graphique intgr

1 crans LCD
Avant toute chose, soyons clairs, il nexiste pas proprement parler dcran tactile. Lcran LCD et la dalle tactile consistent en 2 priphriques diffrents quil va falloir faire interagir (nous verrons a dans le prochain numro). Il existe cependant diffrents types dcrans et diffrentes faons de les adresser. Dune manire gnrale dans lembarqu, lcran LCD est reli via une interface spcifique au contrleur graphique intgr au SoC comme le montre la figure 1. Le processeur crit les donnes graphiques dans le framebuffer, son tampon mmoire reprsentant la zone daffichage, et le contrleur graphique se charge dafficher rellement les pixels lcran. Dans la plupart des cas, lcran LCD piloter ne dispose pas de sa propre mmoire graphique, cette dernire est donc partage avec le reste du systme,

au sein de la mmoire principale. Le framebuffer reprsente donc un espace mmoire fixe, ddi, et protg, sur lequel le processeur va crire des donnes et sur lequel le contrleur graphique va les lire. Certains systmes trs volus peuvent cependant adresser un cran LCD via un second contrleur, intgr lafficheur LCD, qui dispose de sa propre mmoire ddie, mais cest un cas trs rare. Laffichage du framebuffer vers notre cran LCD est donc la responsabilit du contrleur graphique intgr, qui se charge de faire linterface entre le logiciel et le matriel. Diffrents types dinterfaces graphiques existent et il faut donc comprendre quelles sont les capacits proposes par le contrleur graphique de notre SoC. Dans notre cas, notre processeur OMAP4 utilise un contrleur appel DSS2, tel que prsent dans la figure 2. Le composant DSS (pour Display SubSystem), soccupe de piloter les diffrentes interfaces graphiques possibles (DSI, DPI, RFBI, VENC et HDMI) de manire lectronique, avec gestion des signaux et horloges, mais soccupe galement de la composition graphique des diffrentes couches logiques logicielles. Ce dernier, via un ensemble de Managers et Overlays, propres au chipset de TI, permet dinterfacer plusieurs entres et sorties en parallle, mais galement de grer et multiplexer les lments purement graphiques en provenance du framebuffer et les flux vido,

64

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA DCOUVeRTe D'AnDROID : Le SySTme GRAPHIQUe

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Fig. 3: Signaux de contrles et de donnes de linterface DPI

Cette dernire fait intervenir plusieurs signaux de contrles: -H  SYNC, la synchronisation horizontale ; -V  SYNC, la synchronisation verticale ;

PCLK (pour Pixel Clock), la fr- quence dhorloge ;


Fig. 2: Architecture logicielle du composant DSS2 du chipset OMAP4

-D  E (pour Data Enable), notifiant si des donnes sont transmises ; et des signaux de donnes (8 bits par couleur, pour le rouge, le vert et le bleu), chacun transitant sur un fil ddi. Il est donc ncessaire de souder davantage de fils (ici 28) quavec une interface srie. Cette norme a t remplace dans lindustrie par la norme DSI mais fut la rfrence. De par sa forte consommation lectrique, elle peut cependant crer des problmes dinterfrences lectromagntiques. De plus, elle fonctionne dans un seul et unique sens, du processeur vers lcran. Il nest donc pas, en thorie, possible pour le processeur de dtecter et configurer lcran automatiquement (comme nous en avons dsormais lhabitude avec nos crans PC et TV). Certains crans utilisent pour ce faire un lien I2C ou SPI pour changer des informations via le format EDID (pour Extended Display Identification Data), telles que les rsolutions et frquences supportes, mais galement les temporisations associes aux diffrents signaux. Notre cran LCD nutilise absolument pas ce genre dinformations, il va donc falloir renseigner ces valeurs manuellement. Notez que je complexifie volontairement lexercice, mais cest un cas dcole qui finalement arrive trs souvent dans la pratique.

et de superposer le tout. Ce dernier supporte donc plusieurs types dinterfaces pour piloter notre cran LCD, sur lesquelles nous allons revenir: -D  SI (pour Display Serial Interface) est une norme dfinie par lalliance MIPI (Mobile Industry Processor Interface) pour interfacer haute vitesse et via un bus de donnes srie, le processeur (source de limage) et le priphrique LCD (destinataire des donnes). - D PI (pour Display Pixel Interface), galement dfinie par lalliance MIPI, est une interface parallle daffichage des donnes permettant de contrler des crans 16, 18 ou 24 bits. Cest la norme daffichage historique, la moins chre, et celle sur laquelle nous allons nous baser. - RFBI (pour Remote FrameBuffer Interface), est une interface permettant de contrler un framebuffer et un cran distant. - VENC (pour Video Encoder ), permet de convertir notre signal numrique en analogique pour affichage sur une TV dantan.

-H  DMI (pour High Definition Multimedia Interface), permet de faire vhiculer la fois les flux audio et vido et de sinterfacer sur les TV modernes. noter galement le terme LVDS (pour Low Voltage Differential Signaling, frquemment utilis dans la littrature, qui correspond une norme lectrique de transmission de signaux (et accessoirement un connecteur standardis) et non pas une norme dinterface. Cette dernire supporte la fois les transmissions de donnes en srie ou en parallle et, de par sa faible consommation lectrique, est extrmement utilise dans les priphriques embarqus pour interconnecter SoC et un cran LCD.

2 Interface DPI
Nous choisirons donc de nous baser sur une interface DPI, simple piloter et donc expliquer. Je vous laisserai libre choix du modle dcran que vous dciderez dutiliser pour cet exercice et ne dtaillerai pas lassemblage lectronique sur votre carte. Sachez cependant, comme le montre la figure 3, que linterface DPI est une interface parallle.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

65

MObILIT

3 Signaux lectriques LCD


Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20
Revenons quelques instants sur la thorie du signal graphique en termes dlectronique. Les premiers crans cathodiques (CRT) utilisaient un canon lectrons qui balayait lcran de haut (en partant de la gauche) en bas (en arrivant vers la droite) selon un principe appel raster scanning. Le canon gnrait une intensit lumineuse et parcourait lensemble dune ligne (appele scan line), puis steignait et devait revenir en dbut de ligne pour parcourir la suivante et ainsi de suite, comme reprsent sur la figure 4.

LCD ne sont pas capables de fonctionner cette frquence? Il est pour cela ncessaire de jouer sur les temporisations des signaux de donnes, telles que prsentes dans la figure 5.

Fig. 5: Temporisation des signaux LCD horizontaux et verticaux

Quil sagisse de balayage horizontal ou vertical, lenvoi du signal de synchronisation (appel Pulse Width) ncessite un court instant, durant lequel aucune donne valide nest transmise. Deux autres temporisations, appeles Front Porch et Back Porch correspondent aux dures pr et post scanline.
Fig. 4: Temporisation des signaux lectriques LCD

La dure ncessaire au retour horizontal du canon constitue lintervalle de synchronisation horizontale (ou HSYNC, ou HBI pour Horizontal Blanking Interval). Rciproquement, la dure de retour de fin de la dernire ligne au dbut de la premire constitue lintervalle de synchronisation verticale (ou VSYNC, ou VBI pour Vertical Blanking Interval ). Les crans LCD nutilisent plus de canon lectrons et leur affichage est globalement instantan, mais les principes ont t conservs pour des raisons de compatibilit. Dans notre cas, notre cran LCD offre une rsolution WVGA de 800x480 pixels, que nous souhaitons rafrachir 60Hz. Il nous est donc ncessaire dafficher 800x480x60 pixels toutes les secondes, soit une frquence, appele Pixel Clock, estime 23,04 MHz. Mais voil, que se passe-t-il si notre contrleur graphique ou notre cran

Voil pour la thorie. En pratique, chaque cran LCD dispose de ses propres caractristiques physiques, telles que dcrites dans ses spcifications (ou datasheet) et il est ncessaire de les comprendre pour les renseigner dans notre pilote Linux. Le tableau (Figure 6) reprsente donc un exemple de spcifications LCD et la faon dont nous allons les implmenter.
Paramtre Valeur type

HS Period HS Active Time HS Pulse Width HS First Horizontal Data Time VS Period VS Active Time VS Pulse Width VS First Vertical Data Time

TH THd THp THs TV TVd TVp TVs

Fig. 6: Exemple de spcifications matrielles dcran LCD

4 Pilote LCD
Ouf, cen est fini avec laspect lectronique et matriel! Place enfin aux modifications logicielles (il tait temps...). La premire chose faire est donc de modifier les caractristiques de notre noyau. Assurons-nous davoir le support DSS activ, le support pour contrleur DPI, ainsi que le pilote pour cran DPI gnrique.

66

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA DCOUVeRTe D'AnDROID : Le SySTme GRAPHIQUe

ARCH=arm make menuconfig Device Driver Graphics support [*] OMAP2+ Display Subsystem support (16) VRAM size [*] DPI support OMAP2/3 Display Device Drivers [*] Generic DPI Panel

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Les structures de donnes existant dj, lide globale est de modifier le champ omap4_dvi_panel.name pour y faire correspondre notre structure mon_ecran_lcd la place du generic (qui na pas grand sens finalement, chaque cran tant spcifique). Si votre cran nest pas 24 bits, vous pourrez galement le spcifier via le champ omap4_panda_dvi_ device.phy.dpi.data_lines. Notez galement la valeur de canal logique OMAP_DSS_ CHANNEL_LCD2. Par dfaut, et tel que prsent dans la structure suivante:
static struct omap_dss_device *omap4_panda_dss_devices[] = { &omap4_panda_dvi_device, &omap4_panda_hdmi_device, };

Ceci tant fait, reste modifier les sources de notre pilote dcran LCD pour y ajouter le notre. Modifiez donc le fichier drivers/video/omap2/displays/panel-genericdpi.c pour ajouter le contenu suivant au tableau generic_ dpi_panels[ ], les valeurs tant reprises de la figure 6:
/* Mon cran LCD */ { { .x_res = THd, .y_res = TVd, .pixel_clock = FREQUENCE_DE_RAFRAICHISSEMENT * THd * TVd, .hfp = TH THs - THd .hsw = THp, .hbp = THs - THp, .vfp .vsw .vbp = TV TVs - TVd, = TVp, = TVs - TVp,

},

}, .acbi = 0x0, .acb = 0x0, .config = OMAP_DSS_LCD_TFT, .power_on_delay = 0, .power_off_delay = 0, .name = "mon_ecran_lcd",

notre noyau supporte la fois les priphriques DVI (mais il sagit en fait de notre cran LCD) et HDMI. Ceci peut poser des problmes futurs, Android ne supportant quune seule rsolution dcran la fois. Les chances tant faibles sur la capacit de votre cran LCD supporter les rsolutions typiques du HDMI (720p, 1080p), il risque de passer hors spcifications si vous branchez les 2 crans en mme temps. Le plus simple est alors de dsactiver le support HDMI en supprimant la ligne omap4_panda_hdmi_device de la structure prcdente. Une autre alternative est de forcer lcran primaire utiliser le canal logique (LCD2) de notre cran. Ceci peut se faire en passant la valeur suivante en argument de ligne de commandes noyau U-Boot:
omapdss.def_disp=lcd2

Ceci devrait donc suffire faire correspondre les caractristiques de votre cran LCD maison vers votre pilote de priphrique. Au passage, vous noterez que la Pixel Clock relle diffre maintenant grandement de notre premire estimation. Reste maintenant signaler notre SoC OMAP de bien lutiliser. Ceci se fait via modification du fichier arch/ arm/mach-omap2/board-omap4panda.c:
static struct panel_generic_dpi_data omap4_dvi_panel = { .name = "mon_ecran_lcd", .platform_enable = omap4_panda_enable_dvi, .platform_disable = omap4_panda_disable_dvi, }; struct omap_dss_device omap4_panda_dvi_device = { .type = OMAP_DISPLAY_TYPE_DPI, .name = "dvi", .driver_name = "generic_dpi_panel", .data = &omap4_dvi_panel, .phy.dpi.data_lines = 24, .reset_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, .channel = OMAP_DSS_CHANNEL_LCD2, };

Ceci tant fait, il ne vous reste plus qu recompiler votre noyau:


ARCH=arm CROSS_COMPILE=arm-eabi- make zImage

et remplacer le noyau pr-compile de votre carte par votre noyau nouvellement gnr:
cp omap/arch/arm/boot/zImage device/ma_compagnie/mon_appareil/kernel

Recompilez ensuite votre environnement AOSP et redmarrez votre priphrique. a y est, votre cran LCD est dsormais oprationnel et vous devriez dsormais voir le logo Android sanimer jusqu lapparition du menu.

5 Tablette ou tlphone?
Le plus dur est dsormais fait et vous disposez dun cran fonctionnel. Mais jusqu prsent, nous sommes rests dans lunivers Linux et ses pilotes bien connus. Pour Android, ceci ne reprsente pas grand chose hlas. Laffichage basique 2D est oprationnel, certes, mais a sarrte l. Au premier dmarrage, vous constaterez galement labsence de la barre

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

67

MObILIT

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

de menu tactile, indispensable lutilisation de notre priphrique. Cela sexplique par le mode de fonctionnement dAndroid 4.0 qui supporte dsormais la fois les tlphones et les tablettes. Cela impacte laffichage mme de linterface graphique (prsence ou non des menus tactiles et orientation des boutons). Une recherche dans les sources nous prsente des informations intressantes au sein du fichier frameworks/base/policy/src/com/android/internal/policy/ impl/PhoneWindowManager.java:
// Determine whether the status bar can hide based on the size // of the screen. We assume sizes > 600dp are tablets where we // will use the system bar. int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / DisplayMetrics.DENSITY_DEVICE; //tablet resolution width or height may define >= 480 //system according it to use system_bar or status_bar. //and properity sys.devicy.type used to distinguish tablet and phone. int standDp; String deviceType = SystemProperties.get("sys.devicy.type"); if(! "".equals(deviceType) && deviceType.equals("tablet")) { standDp = 480; } else { standDp = 600; } mStatusBarCanHide = shortSizeDp < standDp;

6 Composition graphique
Android est un OS rsolument orient graphique et multi-applications. De ce fait, de nombreux processus peuvent vouloir dessiner quelque chose lcran en mme temps et donc prendre le contrle du framebuffer. Contrairement aux systmes GNU/Linux classiques, Android nutilise pas le serveur de fentres X.org. Dailleurs, bien quOS embarqu, il nutilise pas non plus les compositeurs daffichage que lon peut retrouver au sein des projets DirectFB, Qt ou EFL . Vous laurez devin, encore une fois, les ingnieurs de Google ont dcid dimplmenter leur propre compositeur graphique qui rpond au nom de SurfaceFlinger . Contrairement un gestionnaire de fentres classiques, o un message est envoy chaque fentre (client) pour demander un r-affichage de sa partie de lcran, SurfaceFlinger soccupe lui-mme de composer son cran en superposant les surfaces en provenance des diffrents clients (les applications). On gagne ainsi en stabilit et vite tout artefact visuel, un seul et unique processus contrlant ainsi laccs au framebuffer, tel que prsent dans la figure 7. Il est donc beaucoup plus facile dajouter des effets visuels 3D ou de transparence, SurfaceFlinger grant lui-mme toutes les surfaces affichables. Afin de maximiser les performances (ou surtout pour viter de rendre le systme inutilement lent), les applications crent ellesmmes les surfaces destines tre affiches et les envoient SurfaceFlinger sous la forme dun buffer gr par Binder. Il ny a donc aucune opration coteuse de recopie mmoire dun espace dadressage un autre. SurfaceFlinger traite des objets appels Surface . Ces dernires peuvent tre en 2D ou en 3D, selon les besoins des applications clientes. Comme illustr dans la figure 8, cest chaque application de crer elle-mme sa propre surface et de lenvoyer SurfaceFlinger.

Android se base donc sur la rsolution de votre cran et la densit de pixels de ce dernier pour dterminer son mode de fonctionnement. Dans notre cas (cran 7 pouces de 800x480), la densit de pixels par pouce (ou dpi) vaut 133. La rsolution basse tant 480, notre shortSizeDp vaut alors 576 (donc moins que standDp, savoir 600) et Android naffichera pas la barre de menu. Pour contrer cela, il est possible soit de forcer le mode tablette, soit de jouer sur la densit par pixels en dfinissant sa valeur (et empchant lauto-dtection). Je vous suggre donc lajout de ces 2 paramtres au sein de votre BoardConfig.mk:
PRODUCT_PROPERTY_OVERRIDES += sys.devicy.type=tablet PRODUCT_PROPERTY_OVERRIDES += ro.sf.lcd_density=120

Si on souhaite maintenant un tant soit peu de performances, deffets visuels 3D ou de rendu vido, les choses se compliquent grandement et il est alors temps de rentrer proprement parler dans larchitecture graphique dAndroid pour comprendre de quoi il en retourne.

Fig. 7: Composition graphique des surfaces

68

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA DCOUVeRTe D'AnDROID : Le SySTme GRAPHIQUe

sans passer par le framework Java. Cest notamment trs utilis dans le dveloppement de jeux vido.

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Mais revenons un instant sur la mise en place. Si vous vous souvenez bien du 3me article, prsentant la gnration de la plateforme, nous allons modifier le fichier device/ma_compagnie/mon_ appareil/device.mk pour y ajouter la ligne suivante:
Fig. 8: Passage de surfaces graphiques des applications vers SurfaceFlinger. $(call inherit-product-if-exists, vendor/ti/ panda/device-vendor.mk)

7 API 2D et 3D
Plusieurs API sont disponibles aux applications pour la gnration de surfaces. Tout ce qui est canevas 2D passe par le projet Skia , un framework de rendu 2D encore une fois dvelopp par Google (cf. [10]). Ce dernier permet le rendu de diffrents types dobjets: objets gomtriques 2D classiques, images ou encore textes. Contrairement lhabitude, Skia nest pour une fois pas spcifique Android. Google lutilise en effet galement comme moteur de rendu pour son navigateur Chrome. Lorsque lon souhaite utiliser des canevas 3D, les applications ont cette fois la capacit de passer par les bibliothques OpenGL|ES et EGL , API de rfrence dans le monde de lembarqu et autres consoles de jeux. Dveloppes sous forme dAPI par le groupe Khronos (cf. [11] et [12]), elles offrent aux applications un protocole normalis et multi-plateformes daccs aux ressources de rendu 3D et daffichage lcran. Depuis GingerBread (Android 2.3), le support dOpenGL|ES est dsormais un pr-requis. Android propose cependant un astucieux mcanisme dabstraction des API, permettant de faire cohabiter la fois une implmentation purement logicielle (agl) galement appele software rasterizer (o le traitement graphique est effectu par le processeur) et une implmentation matrielle (hgl), o le traitement est acclr par le GPU (pour Graphics Processing Unit), qui permet de maximiser les performances graphiques. Soyons clairs, avec Android 4.0, il devient inconcevable de ne pas utiliser lacclration matrielle tant les effets visuels sont dvelopps (si tant est que lon souhaite un peu de performance en hautes rsolutions). Limplmentation logicielle se base sur le composant PixelFlinger, lui-mme bas sur le projet Mesa3D (que lon retrouve sur nos distributions GNU/Linux comme implmentation open source de rfrence pour nos cartes 3D) et utilise le projet LLVM pour compiler les shaders 3D la vole sur le systme. Lacclration matrielle, quant elle, est souvent fournie par le constructeur du SoC lui-mme (ou par un partenaire lorsquil nest pas dtenteur de lIP graphique). Cest le cas sur notre SoC OMAP4, dont le GPU est bas sur un PowerVR SGX540 de la socit Imagination Technologies. Dans 99% des cas, les composants OpenGL|ES et EGL sont fournis sous la forme de bibliothques propritaires, tournant en espace utilisateur. Un pilote noyau est galement ncessaire et gnralement fourni sous licence GPLv2. Le lien noyau/bibliothque est cependant trs fort et il est trs souvent ncessaire de sassurer davoir des versions compatibles (ce qui force des migrations noyau) pour que le tout fonctionne. Vous laurez compris, la gestion des couches basses graphiques sur les systmes embarqus Android (mais cest galement le cas pour du Linux classique) nest pas de tout repos et loin dtre propre. noter que les bibliothques OpenGL|ES et EGL font partie du NDK et permettent donc aux dveloppeurs de bas niveau de les utiliser directement

Cette dernire faisait appel, sil existe, au Makefile dextensions propritaires fournies par Google pour notre carte PandaBoard. Le contenu de larchive fournie (disponible via [13] ) correspond bien aux bibliothques dont nous avons besoin:
vendor/ imgtec panda proprietary libEGL_POWERVR_SGX540_120.so libGLESv1_CM_POWERVR_SGX540_120.so libGLESv2_POWERVR_SGX540_120.so ti panda device-vendor.mk

Profitons-en galement pour ajouter la ligne suivante au fichier BoardConfig.mk, qui permet de figer un paramtre indiquant la version OpenGL|ES supporte. Non pas que ce paramtre soit thoriquement ncessaire (Android est cens dtecter cette valeur automatiquement), mais la pratique veut quun certain nombre dapplications (e.g. AngryBirds) refusent de tourner sans cette proprit:
PRODUCT_PROPERTY_OVERRIDES += ro.opengles. version=131072

Notons galement lutilisation du fichier de configuration /system/lib/ egl/egl.cfg, dont le but est de dterminer le type de moteur de rendu utiliser (hgl ou agl). Le contenu de ce dernier se prsente sous la forme suivante:
0 0 android 0 1 POWERVR_SGX540_120

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

69

MObILIT

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Le premier chiffre de chaque ligne indique lidentifiant de lcran (display) et le second sil sagit dacclration logicielle (0) ou matrielle (1). Comme dhabitude, le fichier peut tre inclus trs facilement via un ajout dans notre BoardConfig.mk:
PRODUCT_COPY_FILES += device/ma_compagnie/mon_appareil/egl. cfg:system/lib/egl/egl.cfg

Reste enfin modifier notre configuration noyau afin dactiver le support du pilote pour GPU PowerVR:
ARCH=arm make menuconfig Device Driver Graphics support [*] PowerVR SGX support PowerVR SGX core (SGX 540) PowerVR build type (Release)

et recompiler le tout comme prcdemment indiqu. partir de ce point, vous pouvez rinstaller et redmarrer votre carte, vous disposez dsormais dune acclration 2D/3D matrielle complte et le systme devrait tre on ne peut plus fluide.

8 Architecture graphique
Histoire de remettre les choses dans lordre, profitons de la gigantesque figure 9 pour mieux comprendre la relation entre les diffrents composants du systme. Les diffrentes applications Java peuvent accder aux couches graphiques les plus basses de manire naturelle par communication avec SurfaceFlinger, notre compositeur graphique, et lensemble des oprations de cration de surfaces telles quvoques prcdemment peut se faire par lutilisation de diffrents moteurs de rendu 2D ou 3D que sont les bibliothques Skia et OpenGL|ES. Au plus bas se retrouve un autre composant appel GFX HAL (pour Graphics Hardware Abstraction Library ), partiellement implment via la libhardware. Ce composant, encore une fois trs souvent fourni par le manufacturier lui-mme (et sous forme binaire propritaire) permet une composition matrielle et une gestion optimise de la mmoire graphique. Cest directement le composant SurfaceFlinger qui va interagir avec cette HAL pour afficher les diffrents lments lcran.

Fig. 9: Vue densemble de larchitecture logicielle graphique dAndroid

9 SurfaceFlinger
SurfaceFlinger a donc pour rle de fusionner les surfaces 2D/3D en provenance de diffrentes applications et de crer une image complte afficher partir de l. Pour ce faire, il repose galement sur lutilisation dOpenGL|ES pour permettre lacclration matrielle de diffrentes oprations graphiques telles quagrandissement et rduction de surfaces,

ou simplement de fusion de calques avec transparence. Il utilise un mcanisme simple mais classique de double tampon mmoire (double buffering) pour grer 2 instances de framebuffer. Lun constitue la zone de travail, lautre la zone daffichage. Ceci a pour but dviter les effets de dchirements graphiques ( tearing ) o le processeur est en train de modifier une partie de lcran (nouvelle image) alors que le contrleur LCD est encore en train de dessiner lancienne image. Le dsavantage est bien videmment une consommation mmoire double, mais dans dans notre rsolution de 800x480, cela ne reprsente toujours qu1,5 Mo de mmoire supplmentaire. Le principe du page flipping

70

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LA DCOUVeRTe D'AnDROID : Le SySTme GRAPHIQUe

est utilis, qui consiste alterner dune image lautre le pointeur mmoire du framebuffer sur la premire zone (front buffer) ou la seconde (back buffer).

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Le principe global de fonctionnement de SurfaceFlinger est fort simple, aprs dmarrage du service par le daemon SystemServer: - Rcupration des extensions EGL supportes ; - Cration des surfaces EGL daccs lcran et association au framebuffer ; - R c uprat ion de s ex ten sion s OpenGL|ES et cration du contexte OpenGL|ES ; - Initialisation du GPU et du contrleur LCD ; - Mise en boucle vnementielle: - Attente de transaction de surfaces de la part des applications, - Composition des surfaces pour former une image cohrente, - Rendu de limage sur le framebuffer.

sondes, nergie, vibrateur et Wi-Fi) au sein dune bibliothque lie avec le framework et dun ensemble de modules, pour chaque type de matriel grer, qui seront chargs dynamiquement. Google fournit nativement un ensemble de modules basiques, dont la plupart peuvent tre repris titre dexemple, mais au final, cest bien lintgrateur de dvelopper ses propres modules pour les adapter son matriel. noter que seule la libhardware est lie au framework applicatif. Les modules sont chargs dynamiquement, de par leur nom et via dlopen(), permettant donc aux quipementiers dintgrer un traitement spcifique et de le livrer sous forme propritaire, sans en livrer les sources. Cest un des moyens qua trouv Google pour saffranchir des problmes de licence GPL des pilotes noyau. La partie sensible peut dsormais se faire en espace utilisateur dans une bibliothque propritaire. Dans le principe, les modules sont chargs par la libhardware qui recherche ce qui est disponible dans /vendor/lib/hw, puis dfaut, dans /system/lib/hw. Le format de recherche permet galement de choisir le module depuis une liste du plus spcifique au plus gnrique, via utilisation des valeurs des diffrentes proprits systme que sont ro.product.board, ro.board. platform et ro.arch. Dans le cas qui va nous intresser prsentement ( savoir le composant gralloc), le choix se ferait donc par exemple dans lordre suivant: gralloc.mon_appareil.so, gralloc.omap4.so, gralloc.arm.so, gralloc.default.so, le premier module rencontr tant choisi. Notons justement que, dans larchive fournie par Imagination qui contenait les bibliothques OpenGL|ES et EGL, nous retrouvons justement notre module gralloc pour la HAL:
vendor imgtec panda proprietary gralloc.omap4.so

Nous verrons chacun des diffrents modules de HAL en leur temps au fur et mesure des articles, mais notre proccupation daujourdhui concerne la partie graphique.

11 GFX HAL
Il y a, proprement parler, deux modules intressants : gralloc et hwcomposer, dont vous trouverez les sources par dfaut, dans hardware/
libhardware/modules/{gralloc, hwcomposer}. gralloc (pour Graphics Allocator ) est le module qui va soccuper dinteragir avec le framebuffer. Il permet de dcrire les proprits physiques de lcran (taille, rsolution, frquence de rafrachissement, ...) mais galement dimplmenter la mthode post(), qui permet de dessiner lcran un buffer graphique. Le buffer (lui-mme allou par gralloc) sera crit lors du prochain signal VSYNC reu par le contrleur LCD (souvenez-vous, la fin daffichage dune page) de manire atomique (gralloc soccupant de bloquer laccs la ressource graphique pour viter les conflits). Il est galement possible (mais facultatif) dimplmenter la mthode setUpdateRect() qui permet de ne rafficher quune partie de lcran (via DMA) la demande, au lieu de forcer le rafrachissement complet 60Hz. Cest fort apprciable lorsque lon considre des hautes rsolutions de type 720p/1080p, pour conomiser dautant la bande passante mmoire (qui est, souvenez-vous, commune tout le SoC). Son rle principal, que lon devine son nom, reste cependant lallocation de buffers graphiques en mmoire. Les buffers allous peuvent tre de plusieurs types: texture ou zone de rendu OpenGL|ES, zone de travail du compositeur matriel, de lacclrateur 2D ou de lencodeur vido, ou tout simplement le framebuffer. Hormis le cas simple du framebuffer, vous comprendrez donc quil agit trs troitement avec le GPU. Il nest donc pas rare que le module gralloc soit

10 Hardware Abstraction Library


Android fournit aux diffrents constructeurs un moyen de crer une pseudo abstraction avec le matriel, en supplment de ce que propose nativement le noyau Linux. Globalement, lide est de fournir un lien entre le framework applicatif Java et les pilotes matriels spcifiques chaque constructeur ou chaque SoC, de manire ne pas continuellement rinventer la roue. Cette couche dabstraction matrielle (ou HAL) se retrouve dans les sources de lAOSP sous les composants hardware /libhardware et hardware / libhardware_legacy, le premier tendant remplacer le second, au fur et mesure des diffrentes versions dAndroid. Cette HAL propose une API daccs diffrentes couches matrielles (audio, framebuffer, allocateur mmoire graphique, compositeur matriel, camra, GPS, lumires, NFC,

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

71

MObILIT

LA DCOUVeRTe D'AnDROID : Le SySTme GRAPHIQUe

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

fourni directement au mme titre que les bibliothques OpenGL et EGL. Libre vous cependant, si vous vous sentez lme du hacker puriste de pilotes graphiques libres, dy aller de votre propre implmentation. Enfin, le second module HAL graphique se prnomme hwcomposer (pour hardware composer). Une implmentation de rfrence se retrouve l encore dans hardware/libhardware/ modules/hwcomposer, mais TI fournit galement les sources de son implmentation optimise au sein de hardware/ ti/omap4xxx/hwc. Dans tous les cas, le module se base majoritairement sur lutilisation dEGL pour la cration et manipulation de diffrentes couches graphiques (ou layers) et pour leur appliquer diffrents effets (intersection entre rectangles, rotations, miroir, fusion avec ou sans transparence, ...). SurfaceFlinger interagit directement avec hwcomposer qui, via la mthode prepare(), va le notifier des capacits matrielles disponibles. Ainsi, si la composition matrielle est possible, hwco m poser sen chargera. Le cas chant, cest SurfaceFlinger qui sen occupera de manire logicielle (comprendre: plus lentement).

pour former une animation graphique. Par dfaut, Android recherche ce fichier dans /system/media, mais lutilisateur a la possibilit de le personnaliser via /data/local. Si vous souhaitez rutiliser une animation existante, Internet en est peupl, et il vous suffit den choisir une via [14] par exemple. Si vous souhaitez raliser la votre, pas de problmes non plus. Il vous suffit de crer un fichier de description appel desc.txt, du format suivant:
800 480 24 p 0 0 part0

Conclusion
Nous voici donc arrivs la fin du gros morceau quest la gestion graphique sous Android. Contrairement la gestion audio, que nous verrons dans un article futur, le graphisme est globalement bien gr sous Android, utilisant lacclration matrielle disponible ds quil peut le faire. Vous aurez cependant remarqu lutilisation massive dun grand nombre de blobs binaires propritaires, ces bibliothques tant charges dynamiquement, excutant du code non vrifi et surtout, dpendantes des API de Google. chaque changement dAPI (et donc souvent de version dAndroid), il devient ncessaire davoir les nouveaux binaires adquats de la part du fournisseur. Que se passe-t-il alors lorsquun constructeur dcide de mettre fin au support de son produit pour privilgier le nouveau? Cela signifie gnralement limpossibilit pour lutilisateur de migrer vers une nouvelle version. Mais trve de dbats, notre systme maison avance doucement mais srement. Nous voici donc dsormais capables de dmarrer notre propre systme avec lacclration graphique matrielle ncessaire sa bonne utilisation. Il lui manque cependant encore quelque chose dessentiel: le support dune dalle tactile, permettant son utilisation avec autre chose quun clavier ou une souris. Cest ce que nous aborderons dans le prochain numro avec une plonge dans la couche dentres/sorties dAndroid.

Les 3 paramtres de la premire ligne correspondent respectivement la largeur, hauteur et frquence de rafrachissement (en nombre dimages par seconde) de vos images. Il est possible de ritrer la seconde ligne plusieurs fois. Elle dcrit une partie de lanimation et commence donc par la lettre p. Les 3 paramtres suivants indiquent respectivement le nombre de cycles daffichage (0 pour tourner en boucle), la dure de pause demande avant affichage de la premire image (en nombre dimages) et le chemin vers les images au sein de larchive. Une astuce simple et efficace pour gnrer votre animation partir dune vido existante est dutiliser MPlayer pour en extraire les images, tel que prsent ci-dessous:
mplayer ma_video.avi -vo jpeg:quality=90

12 Boot Animation
Finissons de jouer avec le graphisme par une modification trs simple bien quinutile (et donc indispensable), savoir comment modifier et personnaliser le logo de dmarrage. Si vous vous souvenez de larticle prcdent, nous avions vu que le daemon init dmarre une application appele bootanimation, dont le but est justement dafficher un logo anim, le temps ncessaire au systme dinitialiser le reste des composants. Ce dernier, sous la forme dune application utilisant les bibliothques Skia, OpenGL|ES et EGL que nous avons vu plus haut, se charge douvrir un fichier appel bootanimation.zip, contenant un ensemble de ressources JPEG ou PNG qui seront affiches lune aprs lautre

Rassemblez ensuite votre ensemble de fichiers et gnrez votre archive ZIP sous la forme suivante:
desc.txt part0/f0000.jpg ... part0/f0075.jpg

Rfrences
[10]  http://code.google.com/p/skia/ [11]  h t t p://w w w.k h rono s .org / opengles/ [12]  http://www.khronos.org/egl [13]  https://developers.google.com/ android/nexus/drivers#panda [14]  http://androidbootanimation. com/

Ceci devrait vous fournir une animation personnalise de 76 images et donc dune dure de 3s. Aussi surprenant que cela puisse paratre, nutilisez pas la compression ZIP, juste la fonctionnalit darchivage (option -0) sous peine de rejet.

72

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

LES 4 FAONS dE cOMMANdER !

D'ANcIENS NUMROS
N 100 N 132

COMPLTEZ VOTRE cOLLEcTION

Par courrier : En nous renvoyant ce bon de commande. Par le Web : Sur notre site : www.ed-diamond.com. Par tlphone : Entre 9h-12h & 14h-18h au 03 67 10 00 20 (paiement C.B.) Par fax : Au 03 67 10 00 21 (C.B. et/ou bon de commande administratif)
remplir (ou photocopier) et retourner aux ditions Diamond - GNU/Linux Magazine - BP 20142 67603 Slestat Cedex / France
Rfrence Prix / No
6,50

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

du numro... ...au numro

N 152

Bon de commande

Bon de commande GNU/Linux Magazine


Rf. LM100 LM132 LM133 LM134 LM136 LM137 LM138 LM139 LM140 LM141 LM142 LM143 LM144 LM145 LM146 LM148 LM149 LM150 LM151 LM152 Dsignation
Le serveur PARFAIT + BONUS : plus de 550 Articles de GLMF sur CD Configurez et optimisez un antispam adaptif avec dspam Clustering et systmes de fichiers rpartis Virtualisation avec XEN 4 Besoin d'un annuaire pour enfin tout centraliser ? OPENLDAP - Installation - Scurisation - Rplication Renforcez la scurit de vos connexions distantes avec OPENSSH et les certificats Centralisez la gestion des authentifications X.509 + SSH Dcouvrez les nouveauts DEBIAN 6.0 Simplifiez et automatisez la gestion de votre virtualisation Noyau & CGROUPS Testez le CLOUD Installez une solution Single Sign-On complte et multiplateforme avec Kerberos Jouons avec le Kernel ! Grez vos sources & projets proprement ! - avec Git et Redmine Dbarrassez-vous de votre serveur mail ! Grce Google Visite au cur de l'mulateur QEMU Migrez votre systme de fichiers vers BTRFS ! Crez votre VPN avec OPENVPN Installez votre groupware Kolab Protgez vos applications web

Qt
1

Total
6,50

Prix / Nos
7,50 6,50 6,50 6,50 6,50 6,50 6,50 6,50 6,50 6,50 6,50 6,50 6,50 6,50 6,50 7,50 7,50 7,50 7,50 7,50

EXeMPLe : LM111

TOtAL :
Frais de port France Mtro. : Frais de port HORS France Mtro. :

+3,9 +6

TOtAL :
Voici mes coordonnes postales : Nom : Prnom : Adresse :

HS N 51

du numro... ...au numro

HS N 60

HS N 61

Code Postal : Ville : Tlphone : e-mail :


 Je souhaite recevoir des infos des Edtions Diamond
Je souhaite recevoir des infos des partenaires des Editions Diamond

Bon de commande GNU/Linux Magazine Hors-srie


Rf. LMHS51 LMHS52 LMHS53 LMHS54 LMHS55 LMHS56 LMHS57 LMHS58 LMHS59 LMHS60 LMHS61 Dsignation
Hacks, lectronique & embarqu Dveloppement Android Initiation PYthon Spcial PHP - Introduction, programmation objet et optimisation du code Spcial C & C++ Java - Rendez vos dveloppements multiplateformes ! Carnet de ROOT ZEND Framework 2 Dvelopper des applications web plus rapidement et avec moins de code ? Django 20 Recettes pour dvelopper vos applications Android Crez vos applications Android comme un pro !

Prix / Nos
6,50 6,50 6,50 6,50 6,50 6,50 6,50 6,50 8,00 8,00 8,00

Je choisis de rgler par : Chque bancaire ou postal lordre des ditions Diamond Carte bancaire n Expire le : Cryptogramme visuel : Date et signature obligatoire

http://www.ed-diamond.com

Retrouvez les sommaires et commandez tous nos magazines sur notre site :

Compltez votre collection de


TTc
Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

au tarif promotionnel de 3,25 par numro* !


Les 4 faons de commander !
Par courrier Par le Web
En nous renvoyant ce bon de commande. Sur notre site : www.ed-diamond.com.

Par tlphone Par fax

Entre 9h-12h & 14h-18h au 03 67 10 00 20 (paiement C.B.) Au 03 67 10 00 21 (C.B. et/ou bon de commande administratif)

Vous recherchez un numro spcifique ?

Rendez-vous sur www.ed-diamond.com pour consulter le sommaire dtaill de chaque magazine !


N117 Base de donnes oriente document : APACHE COUCHDB N118 Utilisez GFS NBD over SSH pour votre Stockage rseau N119 B  esoin d'une solution antivirus crdible ? - CLAM AV face aux produits propritaires N120 B  esoin dune PKI libre pour grer HTTPS, SSH, VPN et S/MIME ? PKI OPENSSL en pratique avec EJBCA, JAVA et JBOSS N121 C  omment tester des solutions sans toucher votre infrastructure ? Virtualisez votre rseau ! avec netkit ou vde2 N122 N  ouveauts du Kernel 2.6.32 N123  Crez des modules d'authentification Radius et tendez les fonctionnalits de votre solution SINGLE SIGN-ON N124 C  onstruisez simplement votre portail Wifi captif avec Chilispot et CAS N125 V  ous cherchez une alternative apache ? - CHEROKEE WEB SERVER Rapide, flexible et facile configurer ! N126 V  ous utilisez encore une Apache surdimensionn ? - NGINX HTTP Serveur web et reverse proxy orients performance N127  Vous souaitez optimiser l'accs vos serveurs ? QOS & Contrle du trafic N128  Besoin de scuriser vos systmes ? - Detection d'intrusion - avec l'HIDS OSSEC N129 C  omment tendre vos capacits de supervision ? - Dveloppez vos propres sondes Nagios ! N130 E  t si vous vous dbarrassiez de votre serveur EXCHANGE ? N131 P  OSTGRESQL 9.0 - Installation, configuration, et mise en uvre

Choisissez vos numros dans le tableau ci-dessous :


GNUstep : le petit frre de MacOS X? Caudium, votre prochain serveur Web ! A  prs MySQL & PostgreSQL SAP DB : La base de donnes libre & puissante C  rez un album Photo avec PHP ...et sans MySQL D  veloppez vos applications Mozilla avec XPFE & XPCOM Adamoto Le crash disque vous guette La rponse de Sun Linux ? SOLARIS 10 Dcouvrez et comprenez la technologie GRID Prsentation et installation du Hurd Compression thorie, algorithmes, et programmation VFS : Systme de fichiers virtuel Systmes de fichiers chiffrs Bluetooth - Spcifications, protocoles et configuration Scurisation du Noyau avec PAX Run in memory  Comment fonctionnent les gnrateurs de nombres pseudo-alatoires eCos, une solution libre pour systmes embarqus Greylist Eliminez le SPAM la racine Dploiement de hotspots Wifi scuriss Le point sur Mono .NET Java et les Brevets Ajax Avanc Paravirtualisation XEN & SLO Rpartition de charge N93 N94 N95 N96 N99 Dveloppez vos extensions Firefox PABX Vido avec Asterisk A  dministration et configuration centralises avec Cfengine G  olocalisation de photos numriques Java & JNI Tirez le meilleur de Java

N47 N48 N49 N50 N56 N64 N68 N69 N70 N71 N73 N74 N77 N78 N79 N80 N81 N82 N83 N84 N87 N91 N92

N101 Chiffrez vos disques N102 LTSP 5 Clients lgers N103 PostgreSQL 8.3 N104 Gestion des services avec OpenSolaris N105 Domotique avec MisterHouse N106 Rcuprez vos donnes aprs une Dfaillance RAID N107 Sauvegardez vos bases de donnes MySQL N108 Comment vos utilisateurs traversent votre Firewall N109 Port Knocking - Ne laissez pas la porte ouverte aux intrusions N110 Scurisez votre systme en le migrant vers LVM2 & RAID 1 N111 18 Recettes pour tirer le meilleur de OPENLDAP N112  Besoin dune solution centralise et efficace dADMINISTRATION SYSTME ? Installez et dployez Puppet ! N113 S  ingle Sign-On / SSO et authentification centralise avec CAS-TOOLBOX N114  Dcouvrir, installer et configurer - Passer ZFS ! Le systme de fichiers rvolutionnaire N115 C  rez et personnalisez votre systme DEBIAN 5.0 LIVE sur CD/DVD ou clef USB N116 C  onstruisez et administrez votre VPN L2TP/IPSEC avec OpenSSL, Openswan, PPP et XL2TPD

GNU/Linux Magazine Numro 100 commander sur www.ed-diamond.com

* dans la limite des stocks disponibles.

N01 N46, N51 N55, N57 N63, N65 N67, N72, N75, N76, N85, N86, N88 N90, N97, N98, N135, N147

Numros GNU/Linux Magazine puiss :

Bon de commande remplir (ou photocopier) et retourner aux ditions Diamond - GNU/Linux Magazine - BP 20142 - 67603 Slestat Cedex
Quantit
x

Prix / No
3,25 =

Total

Voici mes coordonnes postales : Nom :

Frais de port France Mtro. : Frais de port HORS France Mtro. :

+ 3,90
NOUS CONSULTER

Prnom : Adresse :

TOtAL :

Je choisis de rgler par : Chque bancaire ou postal lordre des ditions Diamond Carte bancaire n Expire le : Cryptogramme visuel : Date et signature obligatoire

Code Postal : Ville : Tlphone : e-mail :


 Je souhaite recevoir des infos des dtions Diamond
Je souhaite recevoir des infos des partenaires des ditions Diamond

CODe(S)

PHP5: la magie continue


Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

par Stphane Mourey

Nous continuons notre dcouverte des mthodes magiques de PHP en laborant un cache, non sur les proprits de lobjet, mais sur les mthodes.

1 Rappel sur les mthodes magiques


Pour ceux dentre vous qui auraient manqu lpisode prcdent (GNU/Li151), les mthodes manux Magazine n giques de PHP sont une fonctionnalit avance de ce langage, permettant de modifier profondment le comportement attendu des objets de la classe laquelle elle sapplique. La difficult que posent de telles mthodes est quelles se font facilement oublier par le dveloppeur, qui pourrait avoir de grandes difficults comprendre lorigine de certains bogues, surtout dans le contexte dun travail dquipe ou de longs enchanements dhritage dans les classes. La dernire fois, nous avions utilis la _get pour permettre un mthode _ objet de dterminer lui-mme ses proprits, une fois pour toutes. Dans notre exemple, il en avait rsult un code bien plus court et plus lisible, ainsi quun gain de performance notable. Cette fois-ci, notre travail sera plus labor, puisquil sagira dimplmenter un cache automatique sur les mthodes dune classe. Un premier intrt est vident: viter la r-excution inutile dune mthode appele avec les mmes paramtres sans avoir grer le cache lintrieur mme de la fonction. Il y a toutefois un autre intrt, en programmation PHP avance dans le cadre dun projet MVC (Modle/Vue/ Contrleur). Dans ce contexte, il est frquent de dfinir une mthode statique

sur la classe parente des modles, qui cre une instance de cette classe partir de paramtres restreints, typiquement, un identifiant permettant dinstancier un objet PHP depuis un enregistrement en base de donnes. Une telle mthode doit veiller ne pas crer deux objets identiques qui pourraient ensuite voluer indpendamment lun de lautre: lors de lenregistrement de cet objet, une part des modifications serait perdue... Cette mthode doit donc renvoyer le mme objet et ne pas le rcrer. Ce point est simplifi par le fait que PHP passe les objets par rfrence et non par valeur, un simple cache sur la mthode permet donc de rsoudre le problme. Un cache sur la classe parente de tous les modles serait donc une solution dfinitive. En plus des mthodes magiques, nous allons devoir faire appel aux fonctions sur la gestion des fonctions (http:// php.net/manual/fr/ref.funchand.php). Celles-ci peuvent se montrer trs utiles dans le cadre dune programmation objet avance, elles sont cependant assez retorses utiliser. Pour en savoir plus sur les mthodes magiques en gnral, je vous renvoie la page du manuel officiel de PHP qui leur est consacre (http://php.net/ manual/fr/language.oop5.magic.php). Sachez seulement que ces mthodes ne sont pas appeles magiques par hasard : autant leur utilisation peut amliorer grandement votre code de nombreux points de vue, autant les bogues quelles pourraient provoquer sont difficiles dceler... Nest pas Gandalf qui veut!

2 Prsentations des mthodes magiques utiliser


Nous allons travailler avec deux mthodes magiques ici : _ _ call et _ _callStatic. Ces fonctions sont appeles lorsque PHP dtecte un appel une mthode inaccessible (inexistante, protge et appele hors de lobjet ou encore prive et appele hors de la classe qui la dfinit). La premire, _ _call() est appele dynamiquement, cest--dire depuis un objet existant:
$monobjet->maMethodeInaccessibleDynamique();

La seconde, _ _callStatic() est appele de faon statique, cest--dire comme mthode de la classe:
maclasse::maMethodeInaccessibleStatique();

Remarquez que si vous avez la mauvaise habitude dappeler de manire dynamique des mthodes statiques, vous devrez implmenter deux fois le mme traitement (ou le mutualiser dans une mthode que vous appellerez les deux fois) pour couvrir ces deux types dappel. Sachez tout de mme que PHP est considrablement plus performant avec des mthodes statiques que des mthodes dynamiques. En fait, vous ne devriez recourir aux appels dynamiques que si vous avez besoin de $this, et si tel est le cas, vous ne pourrez appeler ces mthodes de manire statique... Tout cela est cohrent.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

75

CODe(S)

3 Convention de nommage
Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20
Comme dans notre prcdent article, nous ne voulons pas rendre accessibles toutes les mthodes inaccessibles de lobjet, mais nous voulons seulement rendre inaccessibles certaines mthodes pour permettre lobjet dutiliser son cache avant dappeler la mthode si ncessaire. Il faut donc que lobjet ait un moyen de dterminer sil doit ou non appliquer ce traitement lors dun appel de mthode inaccessible. Pour y parvenir, nous allons utiliser une convention de nommage: nous allons prfixer toutes les mthodes auxquelles le cache sappliquera par _C_. Ainsi, il nous sera possible dactiver ou de dsactiver le cache sur une mthode simplement en ajoutant ou en supprimant ce prfixe.

_ _call() reoit deux arguments: le premier est le nom de la mthode inaccessible, le second un tableau contenant les arguments envoys cette mthode.

Du nom de la mthode, nous dduisons celui de la mthode cible que nous plaons dans la variable $c a c h e d M e t h o d . Si un appel est fait ousontmeslunettes() et que ousontmeslunettes() nexiste pas ou nest pas accessible, nous allons travailler avec_C_ousontmeslunettes(). Nous utilisons la fonction method_ exists pour savoir si elle existe effectivement. Si tel est le cas, cela signifie que le traitement du cache doit tre effectu. Il peut tre de deux types: soit on trouve la valeur recherche dans le cache, soit on excute la mthode et on place le rsultat dans le cache. Notre cache, nous lavons dit, est un tableau. Pour y stocker les donnes, la premire cl que nous utilisons est le nom de la mthode cache, _C_ousontmeslunettes, dans notre exemple. Le deuxime lment qui nous permet de dterminer si le rsultat recherch se trouve dj dans le cache est la liste des arguments. Ceux-ci nous sont connus sous la forme dun tableau. Toutefois, PHP ne nous permettant pas dutiliser un tableau comme index dun autre tableau (ce qui ne serait dailleurs pas judicieux), nous ne pouvons les utiliser en ltat. PHP nous fournit heureusement une fonction qui permet de convertir un tableau en chane de caractres sans perte de donnes (une autre fonction existe permettant le traitement inverse si ncessaire). Il sagit de serialize(). Mais cette transformation, bien que fonctionnant, nest sans doute pas optimale: il est frquent dappeler une fonction avec des arguments trs complexes et trs lourds, des objets contenant des tableaux de valeurs, dautres objets... Bref, une telle liste darguments peut se rvler trs longue et il nest pas utile de conserver toutes ces informations. Nous allons utiliser le hash md5() des arguments srialiss comme deuxime clef de notre cache:

4 Implmentation dynamique
4.1 Le code
classwithCachedMethods{ var $methodsCache=array(); static $staticMethodsCache=array(); function _ _call($method,$args) { $key = md5(serialize($args)); // traitement de cas particuliers if (substr($method,0,3)==_C_) { if (method_exists($this,$method)) { // la mthode cache a t appele explicitement: on rafraichit le cache return $this->methodsCache[$method][$key]=call_user_func_array(array(get_called_ class(),$method),$args); }else{ // le cache a t dsactiv pour cette fonction, mais le code demande un rafraichissement du cache, on rappelle simplement la fonction $method = substr($method,3); return call_user_func_array(array(get_called_class(),$method),$args); } } // traitement normal $cachedMethod = _C_.$method; if (method_exists($this,$cachedMethod)) { if (!is_array($this->methodsCache[$cachedMethod]) || !array_key_exists($key,$this>methodsCache[$cachedMethod])) { $this->methodsCache[$cachedMethod][$key]=call_user_func_array(array(get_called_ class(),$cachedMethod),$args); } return $this->methodsCache[$cachedMethod][$key]; } } }

Voici donc notre nouvelle classe que nous avons appele withCachedMethods. Nous navons pour le moment implment quune seule mthode, la fonction _ _call, qui prend en charge linterception de mthodes inaccessibles. Par ailleurs, une proprit est dfinie: $methodsCache, qui contient le cache des mthodes sous forme dun tableau. Dtaillons le fonctionnement de notre mthode magique _ _call. Remarquons, en guise de prambule, que le code qui la compose se structure en deux parties. La premire est consacre au traitement de cas particuliers sur lesquels nous reviendrons plus loin. La seconde est le traitement normal, celui qui permet le fonctionnement de notre cache de la faon la plus ordinaire.

76

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

PHP5: LA mAGIe COnTInUe

$key=md5(serialize($args));

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Ensuite, nous dterminons sil existe un cache pour notre mthode et si oui, si ce cache contient la clef correspondant nos arguments. Il est important de vrifier si le cache existe bel et bien (is_array()) avant dy chercher la clef car array_key_exists() peut, selon la configuration et la version de PHP, lever des erreurs. Si une telle clef nexiste pas, il faut crer cette clef et dterminer la valeur qui lui correspond. Ici, il va nous falloir faire appel la fonction fournie par PHP call_user_func_array. Celle-ci permet dappeler une autre fonction en lui passant un tableau darguments de longueur arbitraire, comme si cette fonction cible avait t appele normalement. Par exemple:
functionY($a,$b,$c){ //traitement }

Nous constatons que le premier appel plus() avec comme arguments 1 et 2, puis 3 et 4, nous fournit un rsultat dtermin par la mthode _C_plus, mais que le deuxime appel plus() avec comme arguments 1 et 2 nous fournit un rsultat issu du cache.

4.3 Traitement des cas particuliers


Nous lavons indiqu plus haut, notre mthode _ _call supporte le traitement de certains cas particuliers. Quels sont-ils? Il y en a deux. Dans les deux cas, le code appelant la mthode y accde explicitement en utilisant le prfixe de cache. Cela signifie que le programmeur qui a crit cet appel sait quil sagit dune mthode cache : cest exactement ce quil ferait sil voulait contourner le cache. Cet appel tant tout de mme intercept par _ _call(), cela implique que mme prfixe, la mthode appele reste inaccessible, car elle a t dclare protected et appele extrieurement lobjet. Pour autant, nous nallons pas laisser tomber notre dveloppeur: sil appelle explicitement la mthode de cette faon, cest que le rsultat prsent dans le cache ne le satisfait pas. Peut-tre a-t-il dtect une erreur, ou bien sait-il que la donne est prime suite une action de sa part? Peu importe: nous pouvons interprter cet appel comme une demande de correction du cache. Nous allons donc rappeler la fonction et rafrachir la valeur stocke dans le cache. Toutefois, dans ce cas particulier, se dissimule un autre cas particulier : nous avons dfini que nous pouvions dsactiver le cache dune mthode simplement en supprimant son prfixe (et sa protection). Si nous voulons pouvoir continuer ainsi, il faut galement que notre interception soit capable de traiter le cas o, dune part, le cache aurait t dsactiv pour la mthode et, dautre part, une demande de rafrachissement de cache serait fait pour cette mthode. Dans ce cas-l, il nous faut alors appeler la mthode non-prfixe et renvoyer directement ce rsultat. Ds lors, le code suivant:
print $test->plus(1,2)."\n"; print $test->plus(1,2)."\n"; print $test->_C_plus(1,2)."\n";

Peut tre appele ainsi:


call_user_func_array(Y,array(argA,argB,argC));

Le premier argument de call_user_func_array() permet dappeler une mthode plutt quune fonction lorsquil contient un tableau dont le premier lment est le nom de la classe et le second le nom de la mthode. Et cest ce que nous faisons ici. Il est noter que cet appel est effectu de manire dynamique.

4.2 Le test
Pour tester notre cache, nous allons ajouter notre objet une mthode simple, qui aura pour seule tche deffectuer une addition. Pour savoir si le rsultat que nous obtenons est issu du cache ou non, nous allons ajouter une ligne notre mthode qui affichera un petit texte indiquant que non. Voici donc la mthode que nous ajoutons:
function _C_plus($a,$b){ print "No cache!\n"; return $a+$b; }

Maintenant, crivons encore quelques lignes en dehors de la classe pour la tester:


$test print print print = newwithCachedMethods(); $test->plus(1,2)."\n"; $test->plus(3,4)."\n"; $test->plus(1,2)."\n";

produira:
No cache! 3 3 No cache! 3

Le rsultat sera:
No cache! 3 No cache! 7 3

Voil, nous en avons termin avec la partie dynamique. Nous pouvons donc maintenant passer l...

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

77

CODe(S)

5 Implmentation statique
5.1 Avertissement
Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20
La version 5 de PHP a beaucoup volu dans ses diffrentes sous-versions en largissant les possibilits offertes au programmeur pour utiliser les classes dobjets de manire statique. En ce qui concerne les techniques de programmation dveloppes dans la suite de cet article, il est impratif de disposer dune version de PHP au moins gale 5.3, sans quoi, cela ne fonctionnera pas.

Un peu confus? Prenons un exemple:


class Vador { static $force; static function deQuelCote() { return "Obscur"; } static function faisTonChoix() { return self::deQuelCote(); } static function quelEstTonDestin() { return static::deQuelCote(); } } class Luke extends Vador { static function deQuelCote() { return "Lumire"; } } print Luke::faisTonChoix()."\n"; print Luke::quelEstTonDestin()."\n";

5.2 Le code
Ajoutons maintenant le code suivant notre classe withCachedMethods:
static $staticMethodsCache = array(); static function _ _callStatic($method,$args) { $key = md5(serialize($args)); $calledClass = get_called_class(); // traitement des cas particuliers if (substr($method,0,3)==_C_) { if (method_exists($calledClass,$method)) { // la mthode cache a t appele explicitement: on rafraichit le cache return static::$staticMethodsCache[$calledClass][$method][$key]=forward_static_call_arr ay(array($calledClass,$method),$args); }else{ // le cache a t dsactiv pour cette fonction, mais le code demande un rafraichissement du cache, on rappelle simplement la fonction $method = substr($method,3); return forward_static_call_array(array($calledClass,$method),$args); } } // traitement normal $cachedMethod = _C_.$method; if (method_exists($calledClass,$cachedMethod)) { if (!is_array(static::$staticMethodsCache[$calledClass][$cachedMethod]) || !array_key_exi sts($key,static::$staticMethodsCache[$calledClass][$cachedMethod])) { static::$staticMethodsCache[$calledClass][$cachedMethod][$key]=forward_static_call_arra y(array($calledClass,$cachedMethod),$args); } return static::$staticMethodsCache[$calledClass][$cachedMethod][$key]; }

Un tel code affichera:


Obscur Lumire

Quavons-nous fait? Nous avons dfini une classe Vador avec trois mthodes statiques: dequelCote() qui retourne toujours "Obscur", puis deux autres qui appellent cette premire, mais lune en utilisant self et lautre en utilisant static. Sur la classe Vador, ces mthodes fourniraient toujours le mme rsultat. Mais ds lors que nous les utilisons sur la classe Luke , qui en hrite mais qui redfinit la mthode deQuelCote, il nen est plus de mme et la diffrence entre static et self devient flagrante. Dans notre contexte, nous ne connatrons pas les dilemmes de Luke, nous voulons que nos classes aient chacune un cache bien indpendant, aussi utilisons-nous systmatiquement static dans nos mthodes qui grent le cache.
forward_static_call_array() effectue le mme travail que call_user_ func_array(), mais de manire statique.

Lalgorithme fondamental tant le mme que pour limplmentation dynamique, il ny a rien de surprenant ce que les deux mthodes se ressemblent autant. Les diffrences tiennent au fonctionnement statique. Notons que nous commenons par dfinir une proprit de la classe
$staticMethodsCache, qui contiendra le cache statique. Une telle variable est habituellement appele en utilisant la syntaxe nom_de_la_classe::$nom_ de_la_proprit . PHP permet galement dappeler ces proprits de ma-

nire rflexive et de deux faons diffrentes. A lintrieur dun objet, un appel rflexif est fait en utilisant la variable $this. A lintrieur dune classe, on peut utiliser soit self, soit static. Il y a une grande diffrence entre les deux, qui tient lhritage : self va faire une rflexion sur la classe o il est crit, alors que static va faire une rflexion sur la classe dans laquelle la mthode est excute.

Attention! Il y a une diffrence fondamentale entre le fonctionnement statique et le fonctionnement dynamique, qui si elle nest pas prise en compte au moment dune implmentation statique,

78

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

PHP5: LA mAGIe COnTInUe

pourrait tre lorigine de bogues trs retords: les variables statiques sont hrites par rfrence. Cela signifie que ce code:

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

class maman { static $test; } class fille extends maman {} maman::$test = ko; fille::$test = ok; print maman::$test."\n"; print fille::$test."\n";

naffichera pas:
ko ok

comme on pourrait sy attendre, mais:


ok ok

La solution, si cest un problme, consiste redfinir la variable statique dans la classe fille. Ainsi, avec le code suivant:
class fille extends maman { static $test; }

Les variables statiques $test de la fille et de la mre seront bien diffrentes. Dans notre code, nous ne voulons pas que les caches de lune ou lautre classe se mlangent, simplement parce que ces classes auraient des mthodes synonymes. Mme hrites, elles pourraient fournir des rsultats diffrents, leurs contextes statiques pouvant tre diffrents. Pour pallier cela, nous avons ajout une dimension notre tableau, le premier index tant toujours le nom de la classe appele, tel que donn par get_call_class(). Cette prcaution est suffisante et permet dviter de redfinir le cache dans toutes les classes qui utiliseront cette mthode de cache.

6 Pour finir
Nous avons vu lors de ces deux articles comment implmenter des caches automatiques et puissants sur des classes dobjets PHP en utilisant certaines des fonctions les plus avances de PHP, les mthodes magiques et les fonctions de manipulation de fonctions. Tout cela est bien joli, mais dans un contexte o les dveloppeurs sont amens de plus en plus souvent tendre des classes fournies par des frameworks et PHP ne permettant pas lhritage multiple, cela peut rester lettre morte dans les cas les plus intressants. Heureusement est arriv... PHP 5.4, qui propose les traits pour rpondre cette difficult. Nous aborderons ce concept dans un prochain article.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

79

CODe(S)

01:59:60 : Une seconde SVP !


Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20
par Yves Mettier [Auteur de C en action (2ime dition) paru chez ENI et du guide de survie Langage C paru chez Pearson]

Auriez-vous une seconde ? Nous allons revenir sur cette seconde intercalaire apparue le 1er juillet 2012 dernier juste avant 2h du matin en France et plus prcisment le 30 juin 23h 59min 60s en Temps Universel Coordonn (UTC).

1 Introduction
$ man strftime NOM strftime - Formater la date et lheure [...] DESCRIPTION La fonction strftime() formate les divers champs de la structure tm en fonction de la chane de spcification format, puis place le rsultat dans la chane s de taille max. [...] %S La seconde, sous forme de nombre dcimal (00-60). Lintervalle peut tre suprieur 60 pour autoriser des secondes de rattrapage.

Les suivants, ceux arrivant face leur console de supervision toute rouge le lundi, ont pu profiter de ces rapports de bug et des premiers lments de rsolution. Par chance, telle que la nouvelle sest rapidement rpandue sur Internet, corriger le problme consistait simplement remettre chaque serveur lheure avec la commande date, en dsactivant puis ractivant le dmon ntpd au passage. Notez que les serveurs ne se mettant pas a lheure avec ntpd nont pas eu ce dcalage dune seconde. Le bug ne sest donc pas manifest. Par contre, vous devez alors les remettre lheure le cas chant. Pour un ingnieur systme administrant un grand parc, la problmatique est vite devenue celle quil rencontre souvent : passer un jeu de commandes sur un parc htrogne, en tenant compte des particularits et des exceptions, et sassurer que les commandes sont bien passes.
# /etc/init.d/ntpd stop # date -s "$(LC_ALL=C date )" # /etc/init.d/ntpd start

Une minute de plus de 60 secondes, cela existe et cela est mme prvu, prendre en compte par les programmeurs, comme en tmoigne cette page de manuel. Et puis, en quoi un traitement peut-il tre impact par une minute qui dure 61 secondes ? Linformatique nest pas vraiment conue pour quun nombre de secondes dpassant 60 gnre un dbordement de tampon (buffer overflow). Alors, que sest-il pass dans la nuit du 30 juin au 1er juillet 2012 ?

2 Les problmes
Le problme, tel quil a t ressenti, se manifestait sous forme dune forte charge CPU accompagne dune surconsommation de la mmoire et dautres effets de bord, sur les distributions GNU/Linux avec un noyau de version 2.6.21 ou ultrieure, gnralement excutant un serveur Mysql ou des programmes Java. Prcisons tout de suite que la surconsommation mmoire sest avre tre galement un effet de bord de programmes surpris par cette charge CPU quils provoquaient et, que si MySQL ou Java se sont retrouvs tre les cibles principales de ce bug, rien nempchait dautres programmes de le manifester. Le problme suivant a t didentifier la cause du problme initial. Les premiers sen rendre compte dans le monde ont ouvert des incidents chez leur support respectif et certains sont visibles de tous, tels ceux ouverts chez Mozilla ou Red Hat.

Le problme, le dernier, qui nous intresse ici, cest comment sassurer que les commandes sont bien passes. Une autre faon de formuler ce problme est de savoir dterminer si le bug est encore prsent ou non sur un serveur, telle une menace latente qui risque de se manifester tout moment tant que le serveur na pas reboot ou que la commande date (ou toute autre commande plus complexe rsolvant galement le problme) na pas t excute. Pour le rsoudre, pas dautre moyen que dessayer de comprendre ce bug.

3 Linux et le temps
Avec Linux, le temps se mesure de plusieurs faons. Plus prcisment, pour mesurer le temps, il faut un timer et Linux en dispose de plusieurs. Ceux qui vont nous intresser sont : -u  n timer li lhorloge systme (CLOCK_REALTIME). Sa rsolution dpend de la constante noyau HZ. -u  n timer haute rsolution, li au matriel, appel hrtimer. Sa rsolution dpend du matriel.

80

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

01:59:60 : Une SeCOnDe SVP !

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Le hrtimer a t introduit avec le noyau 2.6.21. Nous allons voir plus loin que le bug est li ce timer. Cela explique pourquoi il ne se manifeste ni sur les systmes dexploitation autres que ceux propulss par Linux (FreeBSD, Solaris, Windows, ...), ni ceux dont la version du noyau est antrieure. Par ailleurs, il est gnralement important davoir un serveur lheure. Ici encore, il existe au moins deux faons de procder, qui ne sont dailleurs pas propres GNU/Linux : - en utilisant lhorloge systme, dont vous avez un jour pris soin de mettre lheure, toujours allume grce une pile ; - en utilisant un serveur de temps (avec la commande ntpdate pour se mettre lheure et avec le dmon ntpd pour ajuster lheure de faon fine).

dattente est dj passe depuis longtemps (depuis une seconde moins un pouillme). Et voici le cur du problme : si vous effectuez une boucle en comptant redonner la main au noyau avec un tel mcanisme, vous vous retrouvez dans ce cas monopoliser un processeur. Il est ensuite possible dimaginer tout dysfonctionnement gnr par un processeur rendu ainsi indisponible.

6 Comment savoir si le systme est impact ?


Au point o nous en sommes, cest relativement facile. Il suffit de coder cette attente (lignes 64 73) et danalyser le rsultat renvoy par clock_nanosleep() (lignes 75 79). Si lheure renvoye par clock_nanosleep() est antrieure lheure systme renvoye par clock_gettime() (test lignes 82 95), le bug se manifeste. Sinon, tout va bien. Voici le code dun tel programme, largement inspir du code de John Stultz publi sur LKML (https://lkml.org/lkml/2012/7/1/203) sous licence GPL.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 /* Leap second timer test * inspired by: john stultz (johnstul@us.ibm.com) * (C) Copyright IBM 2012 * Licensed under the GPL */ #include #include #include #include #include <stdio.h> <stdlib.h> <time.h> <sys/time.h> <sys/timex.h>

4 Attendez une seconde...


Le 1er juillet 2012, voici ce qui sest pass sur les serveurs dont lheure est ajuste avec ntpd. Ce dernier a t inform dajuster lheure en insrant une seconde, la fameuse seconde intercalaire. Sur Linux, un appel adjtimex() et le tour est jou : ntpd a ajout une seconde lhorloge systme CLOCK_ REALTIME. Mais voil, sur un noyau 2.6.21 ou postrieur, il fallait galement mettre le hrtimer jour, ce qui pouvait tre fait avec un appel clock_was_set(). ce moment, et jusqu ce que le bug soit corrig sur le serveur, les deux timers CLOCK_REALTIME et hrtimer ont un dcalage dune seconde. Pour corriger, il faut appeler clock_was_set(). Le plus simple est dutiliser la commande date qui, outre le fait de mettre le serveur lheure, appelle cette fonction.

#define NSEC_PER_SEC 1000000000ULL /* Fonction pour ajouter un struct timespec */ struct timespec timespec_add (struct timespec ts, unsigned long long ns) { ts.tv_nsec += ns; while (ts.tv_nsec >= NSEC_PER_SEC) { ts.tv_nsec -= NSEC_PER_SEC; ts.tv_sec++; } return ts; } /* Fonction pour calculer la diffrence entre * deux timespec */ struct timespec timespec_diff (struct timespec a, struct timespec b) { long long ns; int neg = 0; ns = a.tv_sec * NSEC_PER_SEC + a.tv_nsec; ns -= b.tv_sec * NSEC_PER_SEC + b.tv_nsec; if (ns < 0) { neg = 1; ns = -ns; }

5 Attendre, cela occupe...


Normalement, si vous effectuez des oprations ncessitant lun des deux timers, mais uniquement celui-l, vous ne devriez pas avoir de problme. Cest lorsque vous vous servez des deux la fois que cela va mal se passer. Voici un exemple thorique : - O n demande lheure avec clock_ gettime(CLOCK_ REALTIME,...). Appelons T1 cet instant. - On demande au systme dattendre jusqu T1+p ( p correspondant prcisment la notion de pouillme de seconde) avec clock_nanosleep(CLOCK_REALTIME,...). Si le bug est absent, ce code va mettre votre code en attente le temps dun pouillme de seconde. Si par contre le bug est prsent, le systme nattendra pas et redonnera immdiatement la main. En effet, le hrtimer na pas t dcal dune seconde. Pendant que lhorloge systme tait remise lheure, le hrtimer a pris une seconde davance. En dautres termes, du point de vue du hrtimer, lheure de fin

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

81

CODe(S)

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

a.tv_sec = ns / NSEC_PER_SEC; a.tv_nsec = ns % NSEC_PER_SEC; if (neg) { a.tv_sec = -a.tv_sec; a.tv_nsec = -a.tv_nsec; } return a;

Il bloque un instant puis indique OK . Plus prcisment, il attend un pouillme avant de dire que tout va bien. Excutons-le maintenant sur un systme sur lequel la seconde intercalaire pourrait faire des ravages :
$ test_seconde_intercalaire ERREUR now: 1344470399:147497347 diff: 0:-999984513 rem: 0:0

int main (void) { struct timespec ts; int clock_type = CLOCK_REALTIME; int flag = TIMER_ABSTIME; long long sleeptime = NSEC_PER_SEC / 2; struct timespec target, diff, rem; int retcode = 0; /* Quelle heure est-il ? */ clock_gettime (clock_type, &ts); /* Prparons-nous attendre (sleeptime = un pouilleme) */ rem.tv_sec = 0; rem.tv_nsec = 0; target = timespec_add (ts, sleeptime); /* Attendons */ clock_nanosleep (clock_type, flag, &target, &rem); /* Fin de lattente : quelle heure est-il ? */ clock_gettime (clock_type, &ts); /* Combien de temps avons-nous attendu ? */ diff = timespec_diff (ts, target); /* Le moment de vrit : avons-nous attendu un temps ngatif ? */ if ((diff.tv_sec < 0) || (diff.tv_nsec < 0)) { printf ("ERREUR\n"); printf ("now: %ld:%ld diff: %ld:%ld rem: %ld:%ld\n", ts.tv_sec, ts.tv_nsec, diff.tv_sec, diff.tv_nsec, rem.tv_sec, rem.tv_nsec); retcode = EXIT_FAILURE; } else { printf ("OK\n"); retcode = EXIT_SUCCESS; } exit(retcode); }

Lheure est affiche (1344470399 secondes plus 147497347 nanosecondes depuis lorigine des temps), et la diffrence entre avant et aprs est ngative. Notons aussi que le temps dattente restant est nul (0:0) puisque du point de vue du hrtimer, nous avons dj trop attendu avant mme davoir commenc. Donc ERREUR. Ce programme est compiler et lancer sur tous les serveurs Linux pour voir ltendue des dgts.

7 Comment tester ce programme ?


Avant de mettre au point ce petit programme de test, il faut pouvoir le tester. Le tester signifie le lancer sur un serveur dont on sait quil est sain et sur un serveur dont on sait que le bug de la seconde intercalaire peut se manifester. Obtenir un serveur sain est facile : excutez la commande date comme on la vu. Par contre, pour tre certain de disposer un serveur avec un hrtimer dcal, le plus simple est encore de forcer ce dcalage. Nous reprenons le code de John Stultz :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 /* Leap second timer add * inspired by: john stultz (johnstul@us.ibm.com) * (C) Copyright IBM 2012 * Licensed under the GPL */ #include #include #include #include #include #include <stdio.h> <stdlib.h> <unistd.h> <time.h> <sys/time.h> <sys/timex.h>

Pour compiler ce code avec gcc, vous devez indiquer lditeur de liens dutiliser la bibliothque librt (avec loption -lrt aprs votre fichier source). Si comme lauteur, vous voulez en profiter pour vous amuser avec la nouvelle norme C11, vous devez galement prciser que votre code est conforme la norme POSIX de dcembre 2001 avec la constante _POSIX_C_SOURCE (voyez la page de manuel des fonctions clock_gettime() et clock_nanosleep() ce sujet).
$ gcc --std=c1x -D_POSIX_C_SOURCE=200112L test_seconde_intercalaire.c -o test_seconde_intercalaire -lrt

int main (void) { struct timeval tv; struct timex tx; /* clear TIME_WAIT */ tx.modes = ADJ_STATUS; tx.status = 0; adjtimex (&tx); sleep (2); /* Get the current time */ gettimeofday (&tv, NULL); /* Calculate the next leap second */ tv.tv_sec += 86400 - tv.tv_sec % 86400; /* Set the time to be 10 seconds from that time */ tv.tv_sec -= 10; settimeofday (&tv, NULL);

Excutons ce programme sur un systme sain :


$ test_seconde_intercalaire OK

82

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

01:59:60 : Une SeCOnDe SVP !

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

34 35 36 37 38 39 }

/* Set the leap second insert flag */ tx.modes = ADJ_STATUS; tx.status = STA_INS; adjtimex (&tx); exit (EXIT_SUCCESS);

Nous avons laiss ici les commentaires du code de John Stultz. Le principe consiste calculer quand faire survenir la prochaine seconde intercalaire (lignes 26 29). De tte (ou presque), nous calculons que 86400 est le nombre de secondes dans 24 heures. Cela revient calculer le changement de date. Puis lheure est change pour tre 10 secondes avant ce moment-l (lignes 31 et 32). Enfin, nous ajoutons cette fameuse seconde intercalaire (lignes 34 37). Cest fait (ligne 38). Ce code compile comme le prcdent. Pour compiler avec la norme C11, ajoutez encore -D_BSD_SOURCE pour settimeofday(), puis excutez ce programme. Attention, vous devez avoir les droits suffisants pour changer lheure (autrement dit, tre root). Attendez quelques secondes le changement de date. a y est, vous venez de reproduire ce qui sest pass le 1er juillet 2012 ! Vous pouvez maintenant jouer avec le programme de test. Ce test fonctionne sur votre serveur. Mais lorsque vous allez le faire tester lensemble de votre parc GNU/Linux, vous devrez vous fier non pas la valeur de retour du programme, mais ce quil affiche. En effet, certains afficheront OK, dautres ERREUR, mais pensez que dautres encore afficheront des rsultats compltement diffrents. Vous aurez ainsi un autre genre de message derreur si votre binaire, compil sur une architecture 64 bits, sexcute sur un serveur en 32 bits ou, dans un cas moins probable, si votre serveur inventori Linux savre tre un AIX ou Solaris.

La fois prcdente, ctait le 31 dcembre 2008 (soit en France le 1er janvier 2009 1h du matin). La prochaine est prvue pour... Contrairement aux 29 fvrier qui surviennent tous les 4 ans, les secondes intercalaires dpendent du Temps Universel, dfini par lorientation de la Terre par rapport aux toiles. Lorsque le dcalage entre le Temps Universel et le Temps Universel Coordonn (UTC) est trop important (0,9 seconde maximum), on ajoute une seconde au temps UTC. Mais cela ne se prvoit pas, cela se mesure. Mais lon se rend bien compte que ce dcalage dune seconde na aucune importance au niveau humain, et quau niveau des machines, la modification du temps pose au moins autant de problmes quelle en rsout. Il semble communment admis quil vaudrait mieux supprimer cette seconde intercalaire. Mais dans ce cas, les problmes que cette solution rsolvait se posent nouveau et il faudra trouver une nouvelle solution. Alors, la prochaine fois... Ah oui, la prochaine fois... Le bug est corrig dans le noyau 3.5. Et cest un patch de... John Stultz !

9 Le saviez-vous ?
Une seconde est dfinie depuis 1967 comme la dure de 9 192 631 770 priodes de la radiation correspondant la transition entre les niveaux hyperfins F=3 et F=4 de ltat fondamental 6S de latome de csium 133. Rien voir avec les toiles. Cependant, nous commenons pouvoir effectuer des mesures plus prcises du temps. Il faut sattendre donc devoir redfinir la seconde dans les annes qui viennent... Un jiffy est dfini, dans le contexte informatique, comme le temps entre deux interruptions du timer de lhorloge systme. La dure entre deux ticks de lhorloge systme, de 1 jiffy, correspond 1/HZ secondes. Avec HZ valant 100 ( jusquaux noyaux 2.4 inclus), 1 jiffy valait 0,01 seconde. Notez que depuis le noyau 2.6.0, le jiffy na plus la mme valeur, il valait 0,001s par dfaut (HZ valait 1000) puis 0,04s (HZ vaut maintenant 250) depuis la version 2.6.13. Il est maintenant configurable.

8 La prochaine fois...
La Terre tourne sur elle-mme en 24h et autour du Soleil en 365 jours. Mais cela est imprcis. Tellement imprcis pour la rvolution quil faut ajouter une journe chaque anne bissextile, mais pas les annes multiples de 100 mais quand mme les annes multiples de 400 (comme lan 2000 qui tait finalement bissextile alors que 1900 ne ltait pas). Avec la rotation de la Terre sur elle-mme qui ralentit, la journe sallonge et, comme pour la rvolution, il faut compenser. Cest de l que vient cette seconde intercalaire, venue la premire fois le 30 juin 1972 et nouveau le 31 dcembre de la mme anne. Depuis, chaque 30 juin et chaque 31 dcembre, le Bureau Central du Service International de la Rotation Terrestre et Systmes de Rfrence (il est lobservatoire de Paris) dcide sil faut ajouter une seconde ou non. Comme il sagit de temps UTC et que lauteur a crit cet article en France, il faut ajouter 2 heures pour tenir compte du dcalage horaire et de lheure dt, ce qui nous amenait au 1er juillet 1h 59 min 60s, do le titre de cet article.

Rfrences
- https://lkml.org/lkml/2012/7/1/203 : lexplication de John Stultz lorigine de cet article, ainsi que son code largement rutilis dans cet article. Avec les remerciements de lauteur pour ce mail assez explicite. -h  ttp://fr.wikipedia.org/wiki/Seconde_intercalaire : quelques explications de Wikipdia au sujet de la seconde intercalaire. -m  an 7 time : Panorama des fonctions lies au temps et aux temporisations.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

83

CODe(S)

C++ 11 et GCC
Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

par Laurent NAVARRO [Dveloppeur/formateur freelance Altidev Toulouse]

C++ 11, la nouvelle version de la norme C++, a t approuve en aot 2011 mais son implmentation dans les compilateurs a commence bien avant. Lt dernier, mon article vous parlait de ce qui tait alors connu sous le nom de C++0x et de son implmentation partielle dans les versions GCC 4.3 4.5. Aujourdhui, je vous propose dtudier les nouveauts des versions 4.6 et 4.7 de GCC dans le mme esprit.
a nouvelle version du langage C++ est arrive : elle sappelle C++ 11. Cette nouvelle version a mis beaucoup de temps voir le jour. Un des avantages cette lenteur, cest que de nombreux compilateurs ont commenc la supporter avant la sortie finale de la norme, et que du coup, le support de la totalit des nouveauts de la nouvelle norme sera disponible rapidement dans la plupart des compilateurs, commencer par votre compilateur prfr GCC. Cet article fait suite celui publi lt dernier dans GNU/Linux Magazine HS n 55 : Spcial C & C++. Je conserve le mme objectif de prsenter au dveloppeur C++ comment il peut profiter de cette nouvelle version du langage dans son quotidien. Je vais donc poursuivre avec cet article dans le mme esprit, cest--dire que je ne recherche pas tre exhaustif car de nombreuses volutions du langage sadressent la minorit des dveloppeurs qui dveloppent des bibliothques telles que la STL, qui sont dune complexit qui dpasse le plus grand nombre (moi y compris). Cet article sadresse donc au dveloppeur C++ moyen qui utilise les bibliothques plus quil ne les crit. Comme la dernire fois, le fil rouge de cet article va tre la page suivante

[GCCStatus], qui explique dans quelle

version de GCC les volutions du langage sont apparues. Dans larticle prcdent, nous avions couvert les versions 4.3 4.5 de GCC. Nous allons aborder ici les nouveauts des versions 4.6 et 4.7 (4.7.1 sortie en juin 2012). Nous aborderons les nouveauts du langage, ainsi que celles de la bibliothque Standard C++ / STL (Standard Template Library).

Pour information, ma Debian Squeeze est livre avec une version 4.4.5, Ubuntu 12.04 (LTS) avec la version 4.6.3 et Fedora 17 avec GCC 4.7. Linstallation dune version plus rcente de GCC est probablement un peu complexe, donc, cest vous de voir en fonction de vos comptences systme. Pour nos amis windowsiens, ne soyons pas trop sectaires, MingW est livre avec la toute rcente 4.7.0. Visual Studio supporte dj une bonne partie et la version 2012 complte ce support qui est encore partiel, mais Microsoft annonce quil sera complt par des mises jour intermdiaires. C++ Builder tait un peu en retrait sur C++0x mais promet un bon support de C++11 dans la version prvue pour septembre 2012 (du moins sur le compilateur 64 bits...). Intel C++ compiler supporte une bonne partie. Pour activer C++ 11 dans votre GCC prfr, il faut activer loption -std=c++11

qui remplace -std=c++0x dans la ligne de commandes. Cette option est toujours considre comme exprimentale, cest-dire quil peut y avoir des choses qui ne sont pas encore en conformit avec la norme et que rien ne sera fait pour maintenir une rtrocompatibilit et que vous ne pourrez pas blmer GCC pour cela. La priorit sera de respecter la norme, il vous faudra donc peut-tre modifier votre code dans une future version de GCC.

1 Rappel des pisodes prcdents


1.1 Nouveauts du langage :
Je ne vais pas reprendre ici larticle prcdent, mais juste vous faire un rsum (trs) concis de ce quil sy est dit. Une nouvelle syntaxe dinitialisation uniforme est apparue, permettant dinitialiser tout type de variable. Elle utilise les accolades et permet dcrire ceci :
int a3{3}; int a4={4}; int TableauEntier[3]{1,2,3};

Les listes dinitialiseurs permettent dinitialiser des objets de faon similaire des tableaux et permettent dcrire ceci :

84

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

C++ 11 eT GCC

vector<int> V={1,2,3,4,5}; vector<int> V{1,2,3,4,5}; vector<int> V(5); V={1,2,3,4,5};

Par une version vitant de dclarer une fonction prdicat :


vector<personne> VP={{"Stroustrup","Bjarne"},{"Torvalds","Linus"},{"N avarro","Laurent"}}; // exemple de tri utilisant une expression lambda sort(VP.begin(), VP.end(),[](const personne &G,const personne &D) {return G.Nom<D.Nom; });

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Est apparu aussi le mot-cl auto, qui permet de dduire le type dune variable grce son initialisation (on parle dinfrence de type), on sen sert comme ceci :
auto x=43; for(auto it=V.begin();it!=V.end();it++) cout << *it<<endl;

Les chanes brutes permettent dcrire plus facilement des chanes contenant des antislash (\), des doubles quotes (") ou des retours chariots, elles commencent par un R, ont pour dlimiteur "( et peuvent avoir un dlimiteur configurable :
cout<<R"(Une chaine \tsans tab.)"<<endl;

Les numrations fortement types ou enum class permettent de rduire la porte des identificateurs de lnumration en exigeant quils soient prfixs du nom de lnumration. Elles permettent aussi de spcifier le type sous-jacent utilis par lnumration. Exemple dutilisation :
enum class HAlign {Gauche=0,Centre,Droite}; // Valign utilise un char en sous-jacent. enum class VAlign :char {Haut=100,Centre,Bas}; enum HAlign a; // Les membres du class enum ne sont plus globaux (cest le cot class) a=HAlign::Centre;

Ici, un exemple sur plusieurs lignes avec "azerty(comme dlimiteur :


cout<<R"azerty(On peut ecrire ce quon veut et "mme" revenir la ligne (si on veut) La coloration syntaxique ne suit pas forcement ...)azerty"<<endl;

1.2 La STL
La STL a eu aussi son lot de nouveauts, dont quelques classes dun intrt relatif. -L  a classe array qui est un tableau de taille fixe, une classe tuple et une liste chane simple forward_list. - Des versions par table de hachage de map,set,multimap et multiset nommes unordered_map, unordered_ set, unordered_multimap, unordered_multiset qui apportent frquemment des gains de performance. On retrouve ensuite les pointeurs intelligents (Smart pointers) qui taient dj prsents dans la bibliothque BOOST. On retrouve donc unique_ptr, shared_ptr et son acolyte weak_ptr. La norme introduit un nouveau type de binder plus gnrique que bind1st & bind2nd nomm bind, qui permet au passage de traiter plus de 2 paramtres. Voil un exemple utilisant la nouvelle version du binder :
using namespace placeholders; vector<float> vf = {25, 150, 10, 80}; // Version C++11 cout <<"Nbr element >50 = " <<count_if(vf.begin(),vf.end(),bind(greater<float>(),_1,50)) <<endl;

Est apparu un concept un peu barbare nomm RValue rfrence qui permet dintroduire le concept de dplacement dobjet qui tait prcdemment ralis par une succession de copie + destruction. La partie la plus visible est lapparition de constructeur par dplacement et doprateur daffectation par dplacement qui ont des paramtres avec des && comme ceci :
GrosObjet ( GrosObjet &&Src) {// Constructeur de dplacement, nouveaut C++11 x=Src.x; // On sapproprie la zone mmoire de lobjet source Src.x=NULL; // On invalide lobjet source } GrosObjet& operator =( GrosObjet &&Src) {// Operateur dassignation par dplacement, nouveaut C++11 if(x) // Si lobjet courant est valide. delete x; // On libre dabord sa mmoire x=Src.x; // On sapproprie la zone mmoire de lobjet source Src.x=NULL; // On invalide lobjet source return *this; }

Les expressions Lambda ont pour but de remplacer les foncteurs les plus simples en crivant le code directement au lieu dutilisation. Elles permettent de remplacer :
bool TriPersonneParNom(const personne &G,const personne &D) {return G.Nom<D.Nom; } ... vector<personne> VP={{"Stroustrup","Bjarne"},{"Torvalds","Linus"},{"N avarro","Laurent"}}; sort(VP.begin(), VP.end(),TriPersonneParNom);

des callbacks quils soient fonction C classique, objet fonction ou mthode dobjet. Exemple avec une fonction C classique :
float CBParFonction(int x, int y) {return x+y; } function<float (int x, int y)> UnCallback; UnCallback=CBParFonction; if(UnCallback) // Permet de tester si cest assign. cout<<"Callback = "<<UnCallback(10,30);

function qui peut tre utilise pour stocker indiffremment

Autre nouveaut dans les utilitaires, cest lapparition de

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

85

CODe(S)

1.3 Ce qui a chang depuis GCC 4.5 & errata


Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20
Certaines choses ont chang dans GCC par rapport ce que javais crit la dernire fois. Il nest plus possible dutiliser une liste dinitialiseurs pour affecter un tableau ailleurs que lors de son initialisation. Cela reste possible sur une classe telle que vecteur.
TableauEntier={1,2,3}; // Plus possible. vector<int> V(5); V={1,2,3,4,5}; // Toujours possible

// Version C++ 03 for(vector<int>::iterator it=V.begin();it!=V.end();it++) cout << *it<<endl; // Version C++ 11, GCC < 4.6 for(auto it=V.begin();it!=V.end();it++) cout << *it<<endl; // Version C++ 11, GCC >= 4.6 for( auto x: V) cout << x<<endl;

On remarquera que litrateur devient invisible et que cest directement la valeur qui est manipule. Dans sa version de base, le Range-based for manipule une copie de la valeur, mais il est possible de manipuler une rfrence sur la valeur afin de pouvoir modifier la collection en utilisant la notation suivante :
for( auto &x: V)

Lors de lutilisation dune numration fortement type, il ne faut plus prciser que cest un class enum lors de linstanciation de la variable, enum est suffisant.
enum class HAlign a; // fonctionnait en GCC 4.5 enum HAlign a; // Mais enum seul est suffisant en c++11

Jen profite pour faire un errata de larticle prcdent : Concernant unique_ptr, pour rcuprer le pointeur (pour le passer en paramtre une fonction, par exemple), il suffit dutiliser la mthode get(). Dans lexemple sur les Rvalues, un bug stait gliss dans loprateur = classique, il ne fallait pas faire le if(x) delete x; (copier/coller quand tu nous tiens).

Il est aussi possible de spcifier que cette rfrence est constante, ce qui permettra dviter la copie de lobjet en cours tout en bloquant sa modification.
for(const auto &x: V)

Il est aussi possible de spcifier que la variable de boucle par valeur est constante afin de provoquer une erreur de compilation si vous la modifiez par mgarde.
for(const auto x: V)

2 Nouveauts du langage
2.1 Range-based for (boucle foreach) (GCC>=4.6)
La boucle foreach est prsente dans de nombreux langages. Elle fait son apparition dans C++ 11 sous le nom de Range-based for en tant que syntaxe particulire de la boucle for. Cette boucle permet de parcourir une collection. La syntaxe est la suivante :
for (Type VariableDeBoucle : CollectionAParcourir)

Il nest pas possible de spcifier que la variable de boucle est un pointeur ou un itrateur. Il est aussi possible dutiliser cette boucle sur une liste dinitialiseurs :
for( auto s: {"Bonjour","les","amis"}) cout << s<<endl;

2.2 numration (suite) (GCC>=4.6)


En plus des numrations fortement types est apparue la possibilit de spcifier le type sous-jacent sur une numration classique. Exemple de dclaration dune numration style C avec le type char sous-jacent :
enum VAlignement :char {va_Haut=100,va_Centre,va_Bas};

de cette variable. Voil ce que cela donne sur un tableau dentiers :


int Tableau[]{1,2,3,4,5}; for( auto x: Tableau) cout << x<<endl;

Type sera vraisemblablement souvent remplac par le mot-cl auto qui dterminera automatiquement le type

En plus des tableaux, ce type de boucle est utilisable sur tout objet qui implmente begin() et end(), ce qui est le cas de toutes les collections de la STL. Voil donc lvolution pour parcourir un vecteur :

Cette version introduit aussi la capacit de faire des dclarations forward des numrations. Il est prsent possible (comme pour une classe ou une fonction) de dclarer lexistence dune numration et de ne la dclarer compltement (cest--dire avec ses valeurs) que plus tard.
enum class VAlign; void TestForwardEnum(VAlign Alignement);

86

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

C++ 11 eT GCC

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Il est ainsi possible de dclarer un paramtre de fonction ou un attribut de classe du type dune numration sans avoir dclarer lnumration elle-mme (ou inclure le fichier header qui la dclare). noter que, si cette numration utilise un type sous-jacent spcifique (ce qui ne devrait pas tre le cas le plus courant), il doit tre spcifi dans la dclaration forward. Il y a principalement deux motivations de cette volution. La premire est de rduire le couplage, car il y a pas mal de cas o il nest pas ncessaire de connatre les valeurs dune numration, seule la connaissance du type est ncessaire. Exemple:
void Container::SetAlignement(VAlign Alignement) { for( auto &child: Childs) child->SetAlignement(Alignement); }

Remarque
Juste un petit apart que ma inspir lenvie de cacher les choses de la dclaration forward des enums. Une technique classique pour masquer les attributs contenus dans une classe est de crer une classe qui ne contiendra que les attributs et de nintgrer dans la classe visible quun pointeur vers cette classe qui elle restera compltement invisible en tant dclare dans limplmentation de la classe. Illustration:
ClasseSecrete.h
class ClasseSecrete_members; class ClasseSecrete { public: ClasseSecrete(); ~ClasseSecrete(); std::string GetSecret(); void SetSecret(std::string secret); private: ClasseSecrete_members *MembresSecrets; };

ClasseSecrete.cpp
class ClasseSecrete_members { public: std::string LeSecret; }; ClasseSecrete::ClasseSecrete() { MembresSecrets=new ClasseSecrete_members(); } ClasseSecrete::~ClasseSecrete() { delete MembresSecrets; } std::string ClasseSecrete::GetSecret() { return MembresSecrets->LeSecret; } void ClasseSecrete::SetSecret(std::string secret) { MembresSecrets->LeSecret=secret; }

Dans ce code, le compilateur na pas besoin de connatre le dtail de lnumration, sil sait juste quelle existe et connat son type sous-jacent, il peut travailler. La notion de rduction du couplage stend aussi au niveau des dpendances dans les fichiers den-tte (.h), il nest plus ncessaire dinclure le .h qui dfinit lnumration complte, il suffit de dire que cette numration existe. La seconde motivation des dclarations forward des enums est de pouvoir cacher une numration qui est utilise sur un attribut priv. Dans la version prcdente de C++, il ntait pas possible (simplement) dutiliser un enum priv quon ne dclarait pas dans linterface. Le problme vient du fait quen C++, mme les attributs privs doivent tre dclars dans linterface et leurs types doivent tre connus.

Fichier utilisateur de la classe:


ClasseSecrete CS; CS.SetSecret("I love C++"); cout <<CS.GetSecret()<<endl;

2.3 nullptr (GCC>=4.6)


En C++ (en hritage du C), NULL dsigne un pointeur spcial qui signifie pointeur invalide ou non affect. NULL a pour valeur ladresse 0 qui, dans de nombreux environnements est une

Cela fonctionne car la taille dun pointeur est connue mme si on ne connat pas la taille de la classe pointe. Ainsi, le fichier appelant na pas besoin de connatre les dtails de la classe ClasseSecrete_members puisquil doit juste grer un pointeur. Seule limplmentation de la classe ClasseSecrete a besoin den savoir plus. On arrive ainsi masquer compltement les dtails du stockage des donnes. Cette technique peut aussi tre utilise pour avoir des variantes dimplmentation (par exemple sur du code multi-plateforme) qui requirent davoir des donnes stockes diffrentes.

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

87

CODe(S)

valeur spciale o une application classique nest pas suppose accder (sous certains OS, un accs au 1er Mo de la mmoire provoquera mme une erreur dexcution).

Chez nos camarades qui font du Java, ceci est dj possible et lexprience a montr que ctait largement utilis. Linitialisation peut tre effectue avec des constantes ou des appels de fonctions. Linitialisation ne sera pas effectue si lattribut est dj initialis avec la notation de liste dinitialisation du constructeur suivante:
MaClasse(void *p):ptr(p) {}

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

NULL nest pas un mot-cl mais une macro C qui vaut 0 ou ((void*)0) et une rgle dans le langage dit que la valeur 0 peut tre considre comme un entier ou comme un pointeur. Ceci peut poser, dans certains cas, un problme quand le compilateur doit choisir entre un entier et un pointeur. Par exemple:
void MaFonction(char *v); void MaFonction(int v); MaFonction(NULL);

En revanche, avec la notation suivante:


MaClasse(void *p): {ptr=p;}

Ici, lappel MaFonction(NULL) est ambigu (GCC va dailleurs vous le faire savoir). Afin de pallier partiellement ce problme, un nouveau mot-cl nullptr a t introduit, qui est un pointeur sur ladresse 0 mais qui ne peut pas tre considr comme un entier, du coup MaFonction(nullptr) nest pas ambigu. nullptr peut tre compar nimporte quel pointeur et est galement considr comme un boolen false. Le problme nest que partiellement rsolu. Pour le rsoudre compltement, il aurait fallu en plus supprimer la rgle qui dit que la valeur 0 peut tre considre comme un pointeur, ce qui aurait sans doute pos de gros problmes de rtrocompatibilit. Peut-tre que dans 10 ou 15 ans, si nullptr est adopt, il sera envisageable de faire ce changement (en attendant, loption GCC -Wzero-as-null-pointer-constant sen rapproche un peu). En rsum, nullptr est un synonyme typ de NULL que vous risquez de croiser dans le futur, donc mieux vaut connatre sa signification.

linitialisation aura lieu et sera crase par le code du constructeur. Je vous concde que cest une subtilit la C++, mais dans les faits, limpact sera mineur la plupart du temps.

2.5 Dlgation de constructeurs (GCC>=4.7)


Il est frquent, quand on a plusieurs constructeurs, quil y ait du code commun ces constructeurs. Aujourdhui, une technique classique pour factoriser ce code est dutiliser une mthode prive dinitialisation commune qui sera invoque par les constructeurs. Mais cette technique, en plus de sa lourdeur pour les petites classes, se heurte quelques limitations telles que lutilisation de la notation de la liste dinitialisation du constructeur (MaClasse(x):p(x)) obligatoire dans certains cas. La nouveaut prsente au paragraphe prcdent rsout le problme dans certains cas, mais la dlgation de constructeur est une approche plus complte. Dornavant, depuis un constructeur, il est possible dinvoquer un autre constructeur dans la liste dinitialisation du constructeur. Exemple:
class Maclasse { public: Maclasse():Maclasse(50) {} Maclasse(int p):nbr(p) { } int nbr; };

2.4 Initialisation des attributs non statiques (GCC>=4.7)


Les attributs non statiques (cest--dire les attributs classiques) ne pouvaient tre initialiss que dans les constructeurs. Ceci tait un peu fastidieux quand il y avait pas mal de constructeurs, et que la valeur initiale tait tout le temps la mme et du style 0 ou NULL ( je devrais dire nullptr ;-)). Dornavant, il sera possible dinitialiser les attributs lors de leur dclaration et donc dcrire ceci:
class Maclasse { public: Maclasse() {} Maclasse(void *p) { ptr=p;} private: void *ptr=NULL; int nbr=0; };

Le premier constructeur invoque le second avec une valeur constante. Le constructeur de copie peut lui aussi invoquer un constructeur. noter que le destructeur sera invoqu si une exception est leve dans un constructeur alors quau moins un constructeur dlgu a t excut entirement (car si au moins un constructeur est termin, lobjet est considr comme initialis).

88

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

C++ 11 eT GCC

2.6 Syntaxe de surcharge explicite (GCC>=4.7)


Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20
Parfois, lorsque lon surcharge une mthode lors dun hritage, on peut commettre une erreur difficile dceler, car ne provoquant aucun message du compilateur, mais juste un comportement qui nest pas celui de la surcharge dune mthode dans une hritage quon dsirait. Exemple qui marche:
class Personne { public: Personne(string _Nom):Nom(_Nom) {} virtual void DisBonjour() {cout<<"Bonjour "<<Nom<<endl; } string Nom; }; class Homme:public Personne { public: Homme(string _Nom):Personne(_Nom) {} virtual void DisBonjour() {cout<<"Bonjour Mr "<<Nom<<endl; } }; { Personne* P=new Homme("Laurent"); P->DisBonjour(); }

Le 12 octobRe, un nouVeau numRo HoRs-sRie De LinuX PRatiQue :

SPCIAL

Les cas derreurs les plus frquents sont: - Oubli du mot-cl virtual (appellera toujours la mthode associe au type du pointeur et non celle associe lobjet point). - Erreur dans le nom (oubli dune lettre ou dune majuscule) ou dans les paramtres (mauvais nombre ou type, ex: float devient double ou ajout/perte dun const) qui du coup cre une nouvelle mthode virtuelle au lieu de surcharger lexistante. Afin daider diagnostiquer ces problmes sans casser la compatibilit avec lexistant, 2 nouveaux marqueurs de mthode ont t introduits : final et override. coup si ce nest pas le cas pour une raison quelconque, une erreur sera leve.
virtual void DisBonjour() override {cout<<"Bonjour Mr "<<Nom<<endl; }

override permet de dire que lont fait une surcharge, du

Toutes les Ficelles pouR cReR VotRe pRopRe Jeu ViDo pouR le Web, gRce auX nouVelles Fonctionnalits D'HTML 5 !

si vous prenez lhabitude de toujours ajouter override, le compilateur fera des contrles supplmentaires pour vous aider. Voici par exemple le message derreur qui apparatrait si on dcidait de dclarer la mthode de base const sans changer les classes hritires :
virtual void DisBonjour() const erreur: virtual void Homme::DisBonjour() marked override, but does not override

des rappels sur le game design, la montisation des jeux, les graphismes... de la technique (animations, canevas, polices, localStorage, websockets, musique...) et de la pratique, avec la dcouverte d'outils pour acclrer vos dveloppements

w w w. g n u l i n u x m a g.com

DcouVRiR cHeZ VotRe maRcHanD De JouRnauX Ds le 12 octobRe 2012 !89


GNU/Linux Magazine France N 1 5 3

CODe(S)

Voil comment dune bonne intention, on aurait pu se retrouver introduire un beau bug qui aurait t dlicat dceler. Heureusement, maintenant override et le compilateur vont vous aider.

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Le marqueur final, quant lui, permet soit dempcher une surcharge, soit de se protger dun crasement accidentel par un hritier. Il se place sur lanctre qui dcide quil ny a plus de sens pour un hritier de surcharger une mthode.
virtual void DisBonjour() final {cout<<"Bonjour "<<Nom<<endl; }

Gardez en tte que, afin de ne pas casser la compatibilit avec lhistorique, lutilisation de ces marqueurs est optionnelle. Donc, le compilateur ne vous aidera que si vous vous aidez en utilisant ces marqueurs. Je vous conseille de les utiliser systmatiquement car ce genre derreur subtile est vite arriv.

#include <stdexcept> unsigned long operator "" _b (const char* p) { unsigned long res=0; while(*p) { res<<=1; if(*p==1) res|=1; else if(*p!=0) throw std::range_error("Seuls les 0 et 1 sont autoriss pour les litrraux binaires"); p++; } return res; } auto binaire=0101010_b;

On remarque que la fonction na plus quun seul paramtre (la taille nest prsente que pour les littraux chane). Il faut bien garder en tte que ces littraux sont en fait des appels de fonctions et sont donc excuts lors de lexcution du programme et pour chaque apparition du littral. En termes de performance, cest donc trs diffrent dune excution la compilation. Pour lexemple des binaires, ne jetez donc pas encore vos macros ou la notation GCC 0b0101. Cependant, un espoir dexcution la compilation existe au travers du nouveau concept de constexpr que jai lud, et qui pourrait permettre, dans certains cas, lvaluation dexpression constante la compilation. Le suffixe i est implment pour les complex<double> dans GCC, mais cest une extension historique de GCC et non pas une implmentation de cette nouvelle syntaxe.

2.7 Littraux dfinis par lutilisateur(GCC>=4.7)


Les littraux sont les valeurs crites dans le code: 12.5 est un littral flottant, "Bonjour" est un littral char*. Certains usages possibles pour les littraux dfinis par lutilisateur ont t imagins: - "Bonjour"s qui crerait un objet string. - 10.5i qui crerait un nombre complexe. - 34.5km pour intgrer des units ou faire des conversions. - 10101010b pour traiter les binaires. Pour linstant, seule la syntaxe est disponible, mais je suis sr que dans un futur proche, de nombreux formats de littraux volus seront disponibles dans des bibliothques, voire dans le standard. Il est convenu que les littraux utilisateurs devront commencer par un _, ceux sans _ sont rservs pour de futures standardisations ( je nai aucun doute sur le fait que cette rgle ne sera pas trop respecte malgr le warning de GCC ;-)). Un exemple simple permettant de crer un objet string glan sur le net:
std::string operator "" _s (const char* p, size_t n) { return string(p,n); } auto str="Bonjour"_s;

3 Nouveauts de la bibliothque standard C++


3.1 Gestion des Threads
Le C++ supporte depuis toujours les Threads, mais il manquait une classe standard au langage. Cela est prsent chose faite avec std::thread qui est fortement inspir de boost::thread dans une version plus simple. La plupart des choses que je vais raconter ici sont aussi applicables boost::thread condition de changer quelques #include et quelques noms. Lobjectif ici nest pas de faire un cours de programmation parallle, mais juste de vous expliquer comment mettre en uvre les nouveaux modules de programmation concurrente. La documentation disponible est plutt maigre dans la doc GNU libstdc++. La meilleure source dinformation que jai trouve est le standard lui-mme [C++11Std].

str est de type std::string.

prsent, un exemple traitant des littraux non chane en tant que format binaire :

90

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

C++ 11 eT GCC

3.1.1 La classe std::thread


La classe std::thread est la classe qui encapsule la gestion des threads. Voici un exemple:

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

#include <iostream> #include <thread> #include <chrono> using namespace std; void Write10Point() { for(int i=0;i<10;i++) { this_thread::sleep_for(chrono::duration<int,milli>(200)); cout << .<<endl; } cout << "Worker: . termin" << endl; } void DemoThread() { thread t1{Write10Point}; t1.join(); }

Au niveau du passage des paramtres, une petite difficult peut apparatre si vous souhaitez passer une rfrence en paramtre. Le fait de mettre un & dans la fonction ne sera pas suffisant, il faudra en plus, lors du passage, encapsuler le paramtre dans la fonction ref() :
thread MonThread{MaFonction,LeParamParValeur,ref(LeParamParReference)};

Il est aussi possible dappeler un foncteur, cest--dire une classe surchargeant loprateur () et mme une mthode dun objet en utilisant un binder :
class ClassCharWriter { public: ClassCharWriter(char _c):c(_c){} char c; void operator()() {// Pour appel par operateur () / Foncteur Write10Char(c); } void MyMethod() {// Pour appel par Methode classique Write10Char(c); } }; // Exemple avec un foncteur thread t3{ClassCharWriter(C)}; // Exemple avec une mthode de lobjet SWriter ClassCharWriter SWriter(S); thread t4{bind(&ClassCharWriter::MyMethod,SWriter)}; t3.join(); t4.join();

Cet exemple lance la fonction Write10Point dans un thread spar et attend la fin de son excution (t1.join). La fonction Write10Point affiche 10 points en attendant 200ms entre chaque affichage. La cration dun objet thread suffit lancer lexcution dun thread. Si vous excutez ce petit bout de code sur votre Fedora 17 (et probablement ailleurs aussi), vous risquez de rencontrer quelques difficults. La premire risque dtre que this_thread::sleep _for nest pas reconnue, ceci a une tte de bug et il suffit dajouter de faon peu lgante -D_GLIBCXX_USE_NANOSLEEP aux options du compilateur pour arranger ce problme. Le second problme risque dtre lexcution o le lancement du thread provoquera une erreur de runtime fatale votre programme. Pour rsoudre ceci, il suffira dajouter -pthread comme paramtre du compilateur et du linker. Si vous excutez ce code sur MinGW, a ne marche pas car la classe thread na pas encore t porte. Si vous tes arriv excuter le premier exemple, sachez quil est possible de lancer le thread en passant des paramtres la fonction tout simplement en ajoutant les paramtres la suite du nom de la fonction:
void Write10Char(char c) { for(int i=0;i<10;i++) { this_thread::sleep_for(chrono::duration<int,milli>(200)); cout << c<<endl; } cout << "Worker: "<<c<<" termin" << endl; } thread t2{Write10Char,x}; t2.join();

Quelques explications : t3 a en paramtre lappel dun constructeur, ceci a pour effet de construire un objet (instance dune classe) non nomm. Cet objet a pour dure de vie linstruction qui le contient. Du coup, on pourrait craindre que cet objet soit dtruit avant que le thread ne soit lanc, ce qui poserait un problme. Mais il ny aura pas de problme, car lobjet est copi et le thread est lanc sur une copie. Pour t4, lobjet SWriter est pass en paramtre et le comportement sera le mme, du coup le thread ne sera pas lanc sur SWriter mais sur une copie de SWriter, ce qui dans le cas prsent donne un rsultat similaire. Si vous voulez lancer votre thread sur un objet et non pas sur une copie dun objet, il vous faudra utiliser ref(MonObjet). Pour tre exhaustif, il est aussi possible de lancer un thread sur une expression lambda :
thread t5{ []() {Write10Char(L);} };

Bien sr, comme toujours avec les expressions lambda, il faut en user avec parcimonie. Une fois lanc, il faut soit attendre la fin de son excution avec join(), soit le dtacher avec detach() pour quil conti-

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

91

CODe(S)

C++ 11 eT GCC

nue son excution indpendamment de la vie de lobjet thread. Il ne faut surtout pas laisser lobjet se dtruire sans avoir soit rejoint, soit dtach le thread sous peine de terminer le programme de faon brutale.

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

En parlant darrt brutal, un autre cas darrt brutal est lapparition dune exception non traite dans un thread qui aura pour effet darrter lensemble du programme. Il faut donc veiller toujours avoir un catch global dans chaque thread qui, idalement, tracera lvnement et ventuellement prendra une action adquate si cela est possible. Cependant, il est possible que, comme moi, vous soyez un peu fainant et pensiez quil soit possible davoir un traitement uniforme et simple mettre en uvre pour chaque thread. Une solution consiste emballer notre thread dans un foncteur qui sera catcheur/loggeur de dernier ressort.
struct ExceptionCatcher { ExceptionCatcher(string _ThreadName=""):ThreadName(_ThreadName) {} string ThreadName; template <class F,typename... _Args> void operator()(F f,_Args&&... __args) { try { f(__args...); } catch (exception &e) { cout <<"Exception non catchee dans thread "<<ThreadName<<" : "<< e.what()<<"\n"; } catch (...) { cout << "Exception non catchee inconnue dans thread "<<ThreadName<<"\n"; } } }; thread t1{ExceptionCatcher("Write10Point"),Write10Point}; thread t2{ExceptionCatcher(),Write10Char,x};

#include <mutex> mutex M; void Test1(char c) { M.lock(); Write10Char(c); M.unlock(); } void DemoMutex() { thread T1(Test1,1); thread T2(Test1,2); T1.join();T2.join(); }

Dans cet exemple, les 2 appels


Write10Char se font de faon succes-

sive et non pas parallle car le mutex exclut le second thread pendant quil excute le premier. Ici, lutilisation de lock est trs C-ine et risque de rendre le programme instable (deadlock) si une exception est leve dans Write10Char car le mutex ne sera pas libr. Ceci arrive aussi si vous faites un return avant le unlock. Pour viter ces problmes, on utilisera un gardien qui prendra le mutex et le gardera jusqu ce que le gardien disparaisse. Voil la variante plus C++ :
void Test1(char c) { lock_guard<mutex> LG(M); Write10Char(c); }

Celui-ci, de mon cru, permet de grer les paramtres grce un template variadique (qui est une autre nouveaut de C++ 11 que je ne vous ai pas prsente) et permet de mmoriser de faon optionnelle le nom du thread (cela peut tre utile lors de la lecture des logs). La mthode native_handle() permet de rcuprer un handle propre la plate-forme pour accder au thread systme sous-jacent afin dutiliser des primitives systmes dessus.

La dclaration de la variable LG appellera le constructeur de lock_guard qui appellera M.lock(). Lors de la sortie de la fonction (quelle quen soit la raison), la variable LG disparatra, son destructeur sera invoqu et appellera M.unlock(). La variable LG ne sera pas utilise, seul son constructeur et son destructeur nous intressent. Lutilisation typedef, comme souvent, vous permettra dallger un peu le code.
typedef lock_guard<mutex> mutex_guard; void Test1(char c) { mutex_guard MG(M); Write10Char(c); }

3.1.2 Les mutex


Les classes mutex permettent de grer les besoins dexclusion mutuelle qui sont ncessaires pour grer la problmatique classique de la concurrence daccs des ressources. Un mutex ne peut tre pris quune seule fois au moyen de lock() et est relch au moyen de unlock().Tout appel lock() sur un mutex dj pris suspendra lexcution du thread jusqu ce que le mutex soit libr par le thread qui la pris. try_lock() permet de prendre le mutex sil est libre et retourne false sil est dj pris.

Il existe deux variantes de mutex.

92

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

au sommaiRe Du pRocHain
Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

n6

De la tHoRie la pRatiQue
Le FutuR De la cRYpto : Quel algo De 3 lettRes seRa le pRocHain Titanic ?
tat Des lieuX Du logaRitHme DiscRet

Les mains Dans la cRYptogRapHie

Les eRReuRs ne pas commettRe en pRogRammant De la cRYpto

SHA-3 Vue De lintRieuR


PRotections logicielles contRe les attaQues paR canauX auXiliaiRes

Les RisQues lis SSL/TSS La comptition pouR

CRYpto, RDP et cassage oFFline De session

Minitel Rose et cRYpto : ReVeRse Dune Vieille application 16 bits


Sous rserve de toutes modifications.

paRatRe le 12 octobRe 2012 !


w w w. g n u l i n u x m a g.com GNU/Linux Magazine France N 1 5 3

93

CODe(S)

La premire est recursive_mutex, qui permet au mme thread de reprendre autant de fois quil veut le mutex, quil devra rendre autant de fois quil la pris.

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

La seconde, qui nest pas encore implmente, est timed_mutex qui propose une mthode try_lock_for qui essaye de prendre le mutex pendant un certains temps. Il existe aussi une version plus complte du gardien qui se nomme unique_ lock, qui permet de dverrouiller et verrouiller le mutex en cours dexcution tout en tant dans la porte du gardien. Il est possible de crer ce gardien sans prendre le mutex avec defer_ lock ainsi :
unique_lock<mutex> MyLock(M, defer_lock);

fonction sassure que linitialisation cest effectue avec succs (sans lever dexception) quune seule fois et que tous ceux qui la demandent, sont bloqus jusqu ce quelle soit termine. Cette fonction aide mettre en place une initialisation tardive (lazy initialization) plutt que de faire une initialisation systmatique bien avant quelle ne soit ncessaire dans un des threads.
once_flag of_test1; void DoInitOnce(char c) { cout <<"Init done by "<<c<<endl; } void Test1(char c) { call_once(of_test1,DoInitOnce,c); mutex_guard MG(M); Write10Char(c); }

Cest la variable of_test1 qui gre ltat de linitialisation et lexclusion mutuelle.

3.1.3 Les variables condition (Condition variables)


Les variables condition sont un moyen de sabonner des vnements associs une donne qui est protge par un mutex. Elles constituent un mcanisme de base pour grer un modle producteur/consommateur dans des threads diffrents. Nous allons commencer par un exemple simple qui va nous permettre de faire le tour des mthodes.
#include <condition_variable> mutex Mcv; condition_variable MyCV; char MyData=?; void Consommateur(int No) { unique_lock<mutex> LG(Mcv); while(1) { MyCV.wait(LG); cout << No<<"=>"<<MyData<<endl; } } void Producteur() { thread T1(Consommateur,1); thread T2(Consommateur,2); sleep(1);// On laisse les thread se lancer et se mettre en attente sur la condition { lock_guard<mutex> LG(Mcv); MyData=A; } cout << "notify_one A"<<endl; MyCV.notify_one(); sleep(1); { lock_guard<mutex> LG(Mcv); MyData=B; } cout << "notify_one B"<<endl; MyCV.notify_one(); sleep(1); {

Le second paramtre du constructeur try_to_lock permet dessayer de prendre le mutex de faon non bloquante. Dans unique_lock, on retrouve les mthodes lock, unlock, try_lock des mutex ainsi que owns_lock() et loprateur dvaluation boolenne pour savoir si le mutex associ est pris ou pas. La bibliothque fournit aussi 2 fonctions de gestion des verrouillages multiples. La premire, try_lock(), prend de 2 n paramtres (mutex ou unique_ lock) et va appeler try_lock() pour tous, si un try_lock() choue (retourne false ou lve une exception), unlock() sera appele pour tous ceux qui ont pu tre verrouills. La seconde, lock(), est similaire mais va appeler lock() et va nous garantir de ne pas crer de deadlock. Limplmentation est libre mais il est suggr dutiliser des successions try_lock() et unlock(). Une autre fonctionnalit est fournie, il sagit de call_once. Cette fonction t imagine afin de traiter le besoin dune initialisation unique lance depuis plusieurs threads, mais dont une seule a besoin dtre effectue. Cette

94

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

C++ 11 eT GCC

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

} cout << "notify_all C"<<endl; MyCV.notify_all(); sleep(1); T1.detach(); T2.detach();

lock_guard<mutex> LG(Mcv); MyData=C;

Par exemple, pour un modle 1 producteur avec 1 ou n consommateurs et avec un souhait de ne perdre aucune donne produite, une queue synchronise bloquante peut tre intressante. Nous allons utiliser un exemple dimplmentation basique pour illustrer lutilisation des variables condition dans un cas plus classique. Voil notre classe template queue synchronise/scurise:
#include <queue> template<typename DataType> class Squeue { public: void push(const DataType &data) { unique_lock<mutex> LG(Mutex); Q.push(data); LG.unlock(); CV.notify_one(); } void pop(DataType &ret_value) { unique_lock<mutex> LG(Mutex); CV.wait(LG,[&]{return (!Q.empty());}); ret_value=Q.front(); Q.pop(); } bool is_empty() const { lock_guard<mutex> LG(Mutex); return Q.empty(); } private: queue<DataType> Q; mutex Mutex; condition_variable CV; };

qui donne la sortie suivante:


notify_one A 2=>A notify_one B 1=>B notify_all C 2=>C 1=>C

Nous avons donc 2 threads excutant Consommateur qui ont pour rle de consommer la donne reprsente par la variable MyData quand elle est prte en laffichant avec le numro du thread qui fait lopration. Cette donne est protge par le mutex Mcv et les notifications se feront travers la variable condition MyCV. Donc le producteur prend le mutex pour pouvoir tranquillement crire dans la donne puis libre le mutex et avertit un consommateur travers notify_one(). Le consommateur prend le mutex puis se met en attente avec wait(mutex) sur la condition en y associant le mutex (ou un gardien associ au mutex), ce qui va de faon atomique mettre le thread en attente sur MyCV et librer le mutex (ainsi le producteur pourra produire), lorsque la condition sera notifie, le thread sera dbloqu puis prendra le mutex (il attendra jusqu ce quil soit libre). La mthode notify_all() est similaire notify_one(), mais rveille tout thread en attente sur la condition. notify_all() est plutt adapte avertir un ensemble de consommateurs qui consomment la mme donne alors que notify_one() est plutt adapte pour une donne consomme une seule fois par un seul consommateur. Il faut garder en tte que les notify_xxx ne notifient que les threads qui sont en attente sur un wait . Ainsi, si vous venez dtre rveill par un notify et que vous mettez un peu de temps traiter la donne avant de refaire un wait et quentre temps un notify a eu lieu, vous ne serez rveill qu la notification suivante (une solution consiste garder le mutex pendant le traitement, mais cela rduit le degr de paralllisme). Cest pour cela quil y a souvent un boolen qui dit sil y a des donnes consommer et quil est test sous la protection dun mutex avant de faire le wait. Ce mcanisme est un peu basique pour tre utilis en ltat dans pas mal de cas, mais il servira de base pour implmenter un mcanisme de plus haut niveau plus pratique utiliser.

Les points remarquer sont: Dans push, lutilisation de unique_lock pour pouvoir faire un unlock() avant le notify_one() (cela rduit le risque de rveiller le thread pour quil se bloque ensuite sur le mutex) alors que is_empty() peut se contenter dun lock_guard plus lger. La variante de CV.wait qui prend en second paramtre un foncteur prdicat (dans le cas prsent, une expression lambda est parfaitement adapte), qui est quivalent :
while(Q.empty()) CV.wait(LG);

La prsence de cette mthode confirme bien le fait quune variable condition est souvent utilise avec une condition boolenne pour savoir si des donnes sont prtes ou sil sagit dun rveil intempestif. Pourquoi des rveils intempestifs? tant donn quun thread regarde sil y a des donnes traiter avant de se mettre en attente, alors quune notification est envoye chaque push,

w w w. g n u l i n u x m a g.com

GNU/Linux Magazine France N 1 5 3

95

CODe(S)

C++ 11 eT GCC

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

il est possible quun thread dj rveill traite une donne frachement pousse avant que le thread qui tait endormi ne se rveille pour la traiter. Dailleurs sil ne faisait pas ce test, il risquerait de faire un pop sur une queue vide, ce qui lverait une exception. Cette queue synchronise pourra tre utilise ainsi:
Squeue<char> SQ2; void Consommateur(int No) { char c; SQ2.pop(c); cout << No<<"=>"<<c<<endl; }

#include <future> int CalculMult(int valeur,unsigned multiplicateur) { int r=valeur; while(--multiplicateur) { sleep(1); r+=valeur; cout << "Ajoute "<<valeur<<endl; } return r; } void DemoFuture1() { future<int> Resultat=async(launch::async,CalculMult,6,4); sleep(1); cout<<"Je fais un truc"<<endl; sleep(1); cout<<"Jai fini, jattends le rsultat"<<endl; cout<<"Le rsultat est "<<Resultat.get()<<endl; }

void Producteur() { thread T1(Consommateur,1); thread T2(Consommateur,2); cout << "push A"<<endl; SQ2.push(A); sleep(1); cout << "push B"<<endl; SQ2.push(B); sleep(1); T1.detach(); T2.detach(); }

qui donne la sortie suivante :


Je fais un truc Ajoute 6 Jai fini, jattends le rsultat Ajoute 6 Ajoute 6 Le rsultat est 24

Par rapport lexemple prcdent, lutilisation de cette queue synchronise traite la synchronisation, le transfert des donnes (plus de variable globale) et la problmatique dune production plus rapide que la consommation grce une bufferisation dans la queue. Elle ne rpond par contre pas ce que faisait le notify_all. Peut tre quune queue par thread y rpondrait, cela dpend de ce que lon v eut faire. Cette implmentation est basique, elle pourrait tre complte dattente temporise, mais labsence des timed_ mutex dans limplmentation actuelle nous manquera, ils sont disponibles dans boost.

Ici, la tche est simule par une multiplication qui prend du temps. Le rsultat du calcul sera obtenu par lappel get() qui, en plus de retourner le rsultat, bloquera lappelant jusqu ce que le rsultat soit prt. Si le thread appelant veut savoir o en est lautre tche sans appel bloquant, il peut faire ceci:
if(Resultat.wait_for(chrono::duration<int,milli>(0))!=future_ status::ready)

3.1.4 Les futures


Les futures et leurs comparses les promises sont un mcanisme de transfert de valeurs entre 2 (ou plus) tches. Nous nallons ici, dans un souci de simplicit et parce que je nai pas bien saisi lintrt de faire plus compliqu, nous pencher seulement sur la version simplifie de ce mcanisme, savoir la fonction async. La fonction async va nous permettre de lancer une tche avec des paramtres (ou pas), et plus tard, den rcuprer le rsultat. De plus, un async est aussi capable de remonter dans le thread appelant une exception survenue dans le thread excutant. Un petit exemple:

Suite quelques tests, je suis arriv la conclusion quil ne valait mieux pas dtruire le future gnr par async tant quil ntait pas termin, sous peine darrt du programme (le thread sous-jacent ntant ni joint ni dtach provoque probablement un appel terminate dans son destructeur). Peut-tre quavec lutilisation de la version complte des futures, il est possible de grer ce point. Le premier paramtre de async permet de spcifier le mode dexcution, launch::async dans un thread spar, launch::deferred permet de diffrer lexcution de lappel au moment du get() tout en lexcutant dans la mme thread, javoue ne pas avoir vu trop dintrt cette seconde option. Si le paramtre est omis, cest la bibliothque qui choisit, et dans mon cas, elle avait tendance ne pas lancer de nouveau thread. Du coup, jaurais plutt tendance vous conseiller de spcifier le type de lancement que vous souhaitez.

96

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

CODe(S)

C++ 11 eT GCC

3.2 Math
3.2.1 Amliorations
Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20
La bibliothque mathmatique a t enrichie de nombreuses nouveauts. Je vous en donne quelques-unes qui ont attir mon attention : - cbrt(x): racine cubique ; - hypot(a,b): calcul de lhypotnuse sqrt(a+b) ; - round(x): arrondi lentier le plus proche ; -i  sfinite(x): teste si x est valeur finie/valide (voir aussi : isinf, isnan) ; -i  sgreater(a,b) : teste a>b sans lever dexception si une des valeurs nest pas valide (voir aussi quivalence de >=,<,<=,<>) ; - fma(x,y,z): version rapide de x*y+z. Voir [CppReference] pour plus de dtails.

On voit bien que la distribution uniforme a un nombre similaire doccurrences pour chaque valeur, alors que la distribution normale a plus doccurrences autour de 5 que sur les extrmes. Pensez bien faire le seed si vous ne voulez pas vous retrouver toujours avec la mme squence de valeurs.

3.3 Autres volutions


Quelques autres volutions de la bibliothque standard: Dans les algorithmes: Apparition de all_of, any_of, none_of qui permettent de tester un prdicat sur une collection.
vector<int> Valeurs={10,20,30,40,50}; bool res=all_of(Valeurs.begin(),Valeurs.end(),[](int x){return (x<300);});

Dans les containers:


emplace permet dajouter une valeur en la construisant en mme temps, plutt que de la crer puis de la copier dans le container. emplace(position, arguments au constructeur).
list<string> ls; ls.push_back(string("Chaine 1")); ls.emplace(ls.begin(),"chaine 2");

3.2.2 Gnrateurs pseudo-alatoires


prsent, il y a plusieurs gnrateurs pseudo-alatoires disponibles. Ils se composent dun moteur de gnration de nombre avec de nombreux paramtres (on choisira probablement un des pr-configurs) et ventuellement dun postprocessing permettant de faire correspondre les donnes une loi statistique (uniforme, normale, binomiale, ...). Ici, un exemple avec une loi uniforme et une loi normale.
std::uniform_int_distribution<int> distributionU(0, 10); std::normal_distribution<float> distributionN(5, 2); std::mt19937 engine; engine.seed(static_cast<unsigned int>(std::time(0))); auto generatorU = std::bind(distributionU, engine); auto generatorN = std::bind(distributionN, engine); map<int,int> ResU; map<int,int> ResN; for(int n=0; n<1000; ++n) { ResU[generatorU()]++; ResN[generatorN()]++; } for(auto v : ResU) cout <<setw(2)<<v.first<<" -> "<<setw(4)<<v.second<<" "<<setw(4)<<ResN[v.first]<<endl;

Conclusion
Nous voil au bout de ce second article sur les nouveauts C++ 11. La plupart des nouveauts de c++ 11 ont t prsentes car GCC 4.7 en implmente une bonne partie. Un troisime article viendra peut-tre complter ce qui manque (expressions rgulires et quelques autres choses). Jespre que tout cela vous aura donn envie de tester les apports de ce nouveau C++ quel que soit votre compilateur.

Rfrences
[GCCStatus] http://gcc.gnu.org/projects/cxx0x.html [FAQBjarne] http://www2.research.att.com/~bs/C++0xFAQ. html [Wikipedia] http://en.wikipedia.org/wiki/C%2B%2B0x [Boost] http://www.boost.org [C++11Std] Une des dernires versions du draft du standard C++ 11 : http://www.open-std.org/jtc1/sc22/wg21/ docs/papers/2011/n3242.pdf [CppReference] Site avec doc sur la lib std C++, avec la partie C++ 11 mise en vidence : http://en.cppreference.com/ La doc de la libc++ de GCC : http://gcc.gnu.org/onlinedocs/libstdc++/api.html

qui donne (valeur, nbr occurrence dist. Uniforme, nbr dist. normale) :
0 -> 93 - 17 1 -> 83 - 40 2 -> 80 - 93 3 -> 79 - 144 4 -> 93 - 185 5 -> 108 - 203 6 -> 96 - 165 7 -> 84 - 88 8 -> 94 - 44 9 -> 94 - 13 10 -> 96 7

98

G N U / L i n u x M a g azine France N153

www.gnulinuxm a g . c o m

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Ne QuitteZ plus Vos seRVeuRs Des YeuX !

Actuellement en kiosque !

LMHS 62

Disponible cHeZ VotRe maRcHanD De JouRnauX JusQu'au 26 octobRe 2012 et suR : www.ed-diamond.com

Ce document est la proprit exclusive de FELY ANDRIANANTOANDRO (a_djefe@yahoo.fr) - 10 dcembre 2012 16:20

Vous aimerez peut-être aussi