
Avec un titre comme ca dans une rubrique pour Linux, on s'attend a un article completement impartial et descendant en flamme le produit de Microsoft. En fait, il s'est avere que NT devance un petit peu Linux dans le nombre de fonctionalites proposees mais que tout cela est rapidement gache par la bibliotheque de programmation du systeme (API du kernel), veritable casse-tete chinois.
Dans les systemes modernes, c'est a dire avec multitache preemptif (tant pis pour le Mac OS!), la notion de processus occupe une place importante. Avant tout, un programme executable est un fichier present dans un systeme de fichier et comportant un code en langage machine relogeable (les references d'adresses sont relatives a une adresse de base donnee par le systeme lors de l'execution). Lors du lancement de ce programme, le systeme d'exploitation charge le fichier en memoire soit en partie, soit completement et se prepare a executer le code. Un processus est un element abstrait du systeme permettant de representer un programme en cours d'execution. Un processus doit donc contenir non seulement le code executable mais aussi de nombreuses informations complementaires contenues dans un bloc de control du processus (PCB). Comme le systeme peut interrompre a tout moment une execution (preemption du processus), les informations complementaires comprennent en particulier l'etat du systeme (et donc du processeur) au moment de la preemption. Les valeurs des registres CPU sont ainsi stockees, par exemple le compteur de programme (PC) pour pouvoir reprendre l'execution a l'endroit ou elle a ete interrompue. Le processeur possede un mot d'etat qui reference le bloc de control du processus courant et lorsqu'un processus est preempte par le systeme pour commencer ou continuer l'execution d'un autre processus, il y a commutation de mot d'etat. En anglais, cela s'appelle un context switch. Les autres informations peuvent contenir l'occupation memoire, le temps d'execution, etc. Un processus est aussi associe avec un etat, les etats courants sont :
Un processus s'accapare completement le processeur (ou CPU, excusez-moi pour les abreviations) lorsqu'il est dans l'etat RUN et donc tout l'adressage de ce dernier. Pour communiquer avec d'autres processus, il doit donc passer par une memoire secondaire comme un fichier sur disque. Il existe quand meme une hierarchie entre les processus (arbre pere-fils) qui permet de faciliter cette communication mais il est tout de meme difficile de partager des ressources. Pour combler ce manque, les systemes d'exploitation utilisent des threads. Un thread ou cheminement est defini comme une execution possible pour un processus donne. Ainsi, tout processus est associe a au moins un thread qui correspond a l'enchainement des instructions composant le code du programme et donc du processus. Pour l'instant, je suis sur que vous ne saisissez pas forcement la distinction entre thread et processus. Mais il faut savoir qu'un processus peut est associe a plusieurs threads. Ainsi, on peut avoir plusieurs executions simultanees (bien sur, pour la CPU, c'est toujours sequentiel) dans un meme processus. Le grand avantage de cette methode est que les threads partagent le meme contexte et peuvent donc partager les ressources d'un unique processus sans passer par des fichiers d'echanges. Le principal inconvenient est que c'est l'utilisateur (et non le kernel) qui doit maintenant synchroniser les threads. Par exemple, supposons qu'un thread ecrive des donnees dans un tableau et qu'un autre lise ces donnees, si la lecture d'un element donne a lieu avant son ecriture, le programme sera surement corrompu. Le systeme doit donc fournir des outils de synchronisations comme les semaphores, les moniteurs. Ces objets servent a garantir l'execution en exclusion mutuelle de sections critiques, parties de programme qui ne doivent pas etre preemptees.
Maintenant que nous avons fait le tour de la gestion des processus (il y a encore des millions de choses a dire mais je ne suis pas en train d'ecrire la bible des OS !), il serait interessant de comprendre ce que Linux et NT proposent.
NT et Linux sont des OS multitaches preemptifs (ou multiprogrammes) et comportent donc une gestion avancee des processus. Ainsi tout programme execute est associe avec un processus et donc un PCB. Les priorites sous NT divisees en quatre classes :
La classe Realtime rassemble bien sur les priorites les plus elevees. Avec Linux, comme pour tout les Unix, les distinctions sont faites en fonction du facteur nice.
Linux supporte les threads mais (dans la version 1.2.13) seulement dans le kernel, il n'y a pas de threads user tandis que NT dispose d'un ensembles de routines permettant la gestion de multiples threads pour l'utilisateur.
L'architecture memoire de NT est assez simple, chaque processus est associe avec un espace d'adressage virtuel de 4go (forcemement en 32 bits). Cet espace comporte quatre regions ou partitions :
Vous avez donc compris que les processus utilisateurs disposent de 2go d'espace d'adressage, ce qui est relativement confortable. La memoire est paginee par pages de 4k pour les PC ou 8k sur Alpha. Ainsi, pour associer un espace memoire physique a une region de memoire virtuelle, le systeme alloue d'abord des pages dans la zone d'adressage (allocation virtuelle) puis associe une zone physique elle-aussi divisee en pages - avec cette zone virtuelle.
Vous pensez que 95 est un NT "booste" pour supporter les applications DOS ou Win16 ? Eh bien c'est ce que cela devrait etre mais on est loin du compte. Pour donner un petit exemple des concessions faites par microsoft pour lancer 95 rapidement, sachez que la zone du systeme est completement accessible par l'utilisateur ! C'est la premiere chose qu'un systeme doit eviter pour qu'on puisse lui attribuer le statut de systeme stable ! Mais revenons a nos moutons, nous sommes en train d'etudier des systemes d'exploitation !
Chaque processus cree (avec fork() ) sous Linux dispose de 4go d'adressage, bien evidemment mais le dernier giga est reserve au kernel donc il reste 3go utilisable. L'allocation se fait aussi par pages de 4ko, comme pour NT.
L'architecture memoire de NT et de Linux sont donc assez proches et ne permet pas de les departager. Signalons quand meme que NT permet de creer des fichiers mappes en memoires. C'est a dire que l'on peut allouer une zone dans l'espace d'adressage utilisateur (2Go) qui correspond a un gros fichier de donnees. Lorsque l'on veut lire ou ecrire des informations sur ce fichier, des pages sont allouees comme si le fichier se trouvait completement en memoire central. Je n'ai rien lu de tel sur le noyau 1.2.13 de Linux, meme si on m'a dit que c'etait prevu. On donnera donc dans le doute un petit avantage a NT.
N'oublions pas que Linux est gratuit, livre avec les sources et accompagne d'une multitude de librairies permettant au programmeur d'intervenir a differents niveaux du systeme. La plus basse couche consiste en la modification directe du noyau pour rajouter des fonctionnalites. C'est la tache du hacker et il ne faut surtout pas intervenir a ce niveau pour creer des applications. La librairie systeme de Linux permet de creer des processus, de gerer les allocations memoire, les entrees-sorties, etc. Les fonctions systemes sont tres bien documentees et standardisees dans le monde Unix grace a la compatibilite POSIX. En clair, il n'y a presque rien a en dire (quelques points mal documentes, un support BSD incomplet) mais dans l'ensemble, Linux est au Top !
En guise d'exemple, un simple appel de la fonction fork() permet de creer un processus fils au processus courant avec les memes proprietes. Pour allouer de la memoire, on utilisera simplement la librairie ANSI standard (malloc(), free() ) pour ne pas s'embeter et pour gerer les entrees-sorties on utilisera les appels systemes read() et write().
Pour NT, c'est une toute autre histoire, l'interface de programmation se situe dans l'API, c'est a dire que la programmation du systeme se situe au meme niveau que la programmation de l'interface graphique, bref, tout est melange. Un bon exemple vaut mieux que toutes les explications, donc voici comment creer un processus avec NT :
On utilise la fonction :
BOOL CreateProcess( LPCSTR lpszImageName,
LPCSTR lpszCommandLine,
LP_SECURITY_ATTRIBUTES lpsaProcess,
LP_SECURITY_ATTRIBUTES lpsaThread,
BOOL fInheritHandles,
DWORD fwdCreate,
LPVOID lpvEnvironment,
LPSTR lpszCurDir,
LPSTARTUPINFO lpsiStartInfo,
LPPROCESS_INFORMATION lppiProcInfo);
Ouf ! Ca y est, c'est termine. Bon, nous n'allons pas rentrer dans les details des arguments mais sachez qu'il va falloir fixer des attributs de securite pour le processus et son thread principal, allouer des structures pour controler la relation avec le processus pere, etc. Et tous les appels Win32 sont dans la meme veine. Si en plus on rajoute le code de l'interface qui est completement melange avec le code systeme, on finit par tout melanger et jeter NT par la fenetre !
Nous avons vu que NT permettait la creation de fichiers mappes en memoire, etudions pour terminer ce tour d'horizon la creation d'une telle representation memoire :
On va d'abord utiliser la fonction CreateFile avec 7 arguments dont les attributs de protection du fichier. On utilise ensuite la fonction CreateFileMapping (6 arguments) qui fixe entre autres les attributs de protection de l'objet kernel associe au fichier ouvert precedemment. Ensuite on va mapper les donnees du fichier dans l'espace d'adressage du processus par un appel a MapViewOfFile (5 arguments) en recommencant encore une fois la definition des attributs de protection de l'acces a l'objet kernel representant le fichier physique ! En clair, on redefinit trois fois les memes choses, a tel point que l'auteur de [1] se pose la question du but de cette redefinition ! Tant NT que Linux ne sont pas des systemes dits securises mais ils sont quand meme tous les deux assez bien proteges, et Linux ne demande pas d'incessantes initialisations.
Bien entendu, nous n'avons fait qu'un petit tour d'horizon des deux systemes dans trois domaines orientes systeme. On note que NT dispose de plus de fonctionnalites que Linux 1.2.13 comme par exemple la gestion de plusieurs processeurs, le multi-thread ou encore les fichiers mappes en memoire. Mais n'oublions pas que Linux evolue plus vite que son confrere (beaucoup plus vite !) et que le noyau 2.0 apporte, entre autres, le multi-threads utilisateur et le SMP (gestion de 32 processeurs). Mais le nombre de fonctionnalites d'un systeme d'exploitation n'est pas la caracteristique la plus importante. Il faut aussi que ces fonctionnalites soient facilement utilisables, et ce n'est certes pas le cas de NT. Il semblerait que Microsoft veuille absolument imposer une nouvelle maniere de programmer, on pourrait l'appeler la programmation orientee prise-de-tete !
Editions Microsoft Press
ISBN 1-55615-677-4
Un livre tres interessant sur un systeme lui aussi interessant mais vous le verrez comme je l'ai vu, l'API et la lenteur du systeme rendent vite l'utilisation de NT insupportable.
Editions SSC
ISBN 0-916151-89-1
Un livre tres attendu fait par un professeur qui aime beaucoup Linux mais malheureusement, l'auteur veut trop faire le tour de tout ce qui compose un systeme d'exploitation sans assez parler du cas de Linux. Un livre decevant, donc.
Livre gratuit faisant parti du Linux Documentation Project
Present dans Linux Bible, Doctor Linux ou sur CD (distributions de Linux).
Un des ouvrages les plus interessants du LDP meme si certains points sont peu detailles, si vous voulez explorer le kernel de Linux, choisissez ce livre comme support.