Projet système PC : 2014 - AUBERT Bastien, PESEZ Stéphane, VINCHON Arthur

De Ensiwiki
Aller à : navigation, rechercher
smashOs
SmashOs Screenshot.png
Projet Système d'Exploitation 2014

Développeurs Aubert Bastien, Pesez Stéphane, Vinchon Arthur

Présentation

Ceci est la page qui présente le résultat de notre travail lors du projet de spécialité de deuxième année à l'Ensimag.
Le sujet choisi est le projet système qui consiste en l'écriture d'un système d'exploitation pour une machine nue.

Objectifs

Le but est de partir du minimum, c'est à dire l'ensemble des mécanismes d'initialisations qui visent à démarrer la machine, et d'implémenter l'ensemble des fonctionnalités nécessaires au bon fonctionnement de l'ordinateur.

Déroulement

Le sujet décompose naturellement le projet en 7 phases. Il est conseillé (et à juste titre) d'implémenter les phases dans le bon ordre, en s'assurant que chaque partie est bien testée et déboguée avant de passer à la suivante.

Phase 1

La première phase consiste principalement en la prise en main de l'environnement de travail. On découvre les sources fournies, et on installe les différents logiciels nécessaire au projet :

  • qemu : émulateur de machine nue
  • bochs : émulateur de machine nue plus précis
  • unetbootin : logiciel pour installer le noyau sur clé usb, et pouvoir démarrer sur une machine

L'utilisation est expliquée sur le wiki.
On implémente lors de cette phase tout ce qui gère l'affichage graphique, et qui servira tout au long du projet pour déboguer.

Phase 2 et 3

On implémente ici toute la gestion des processus et du timer.

  • Processus :
    • Implémentation d'un ordonnanceur (les différents processus se partagent le temps d’exécution)
    • Utilisation de files de priorités (les processus les plus prioritaires passent en premier)
    • Gérer les différents états des processus (élu, activable, zombi, asleep, blocked...)
  • Timer
    • Gestion de l'interruption timer (le noyau est prévenu de manière régulière)
    • Possibilité "d'endormir" les processus (ils attendent un certain temps inactif)

Toutes ces fonctionnalités ont pour but de gérer l'ensemble des opérations que l'on effectue sur l'ordinateur.

Phase 4

Dans cette phase, on implémente les files de messages pour les processus. Grâce à cela, ils peuvent communiquer sommairement entre eux en échangeant des entiers. Ainsi, on gère des files, dans lesquels les processus peuvent récupérer ou déposer un entier. Ils se bloquent s'ils essaient de récupérer un message dans une file vide, ou s'ils veulent en déposer un dans une file pleine, en attendant qu'un autre processus change l'état de la file. Ces files de messages permettent par extension de créer des mutex ou des sémaphores (une file de capacité 1 peut être vu comme un mutex par exemple).

Phase 5

Il s'agit de la phase la plus longue. Elle nécessite un grand effort de compréhension et de persévérance.
Le but de cette phase est d'implémenter la mémoire virtuelle. Il s'agit faire croire au différent processus que leur mémoire est bien plus grande que celle réelle (4Go au lieu de 256 Mo dans ce projet), et de transcrire en caché chaque adresse virtuelle (entre 0 et 4Go) une adresse physique (une qui existe réellement, et qui est libre entre 0 et 256Mo).
Ainsi chaque processus se partagent la mémoire physique mais cela est caché aux yeux de chaque processus.
Une fois cela en place il faut mettre en place la séparation entre le noyau et les processus utilisateur :

  • Partie noyau

Cette partie possède tous les droits, peut effectuer n'importe quelle action (afficher à l'écran, modifier la mémoire, etc...)

  • Partie user

Il s'agit là de tous les processus que l'on lance sur la machine (test, shell, ...). Leurs accès sont contrôlés par le noyau :
- impossibilité de modifier la mémoire autre que la leur
- impossibilité d'effectuer des actions du noyau
Pour effectuer une action tel que l'affichage à l'écran, ils doivent passer par le noyau grâce à des appels système. C'est une grosse partie de cette phase également, il faut réaliser une bibliothèque d'appels système pour tous les besoin des utilisateurs. Par exemple :
- printf (affichage à l'écran)
- cons_echo (pour l'écho de la console)
- start (pour démarrer un processus)
- music (pour jouer un morceau de musique)

Phase 6

Dans cette partie, on réalise une console. C'est à dire, un processus qui lit les entrées clavier de l'utilisateur. On a donc besoin de gérer les différents événements qui arrivent lorsqu'on presse une touche du clavier.
Il faut également implémenter une fonction qui lit l'entrée au clavier lorsque la touche "entrée" est pressée. C'est une primitive nécessaire pour le shell qui sera implémentée après. Ainsi, le processus de la console se bloque (laisse la main à d'autre processus) en attendant que l'on tape des touches (qui seront stockées dans un buffer) et qu'on finisse par entrée (on traite alors les caractère contenus dans le buffer).

Phase 7

Dans cette phase, on implémente un shell, donc un interpréteur de commande. On lit les entrées clavier de l'utilisateur et on effectue les actions correspondantes s'il en existe. Voici la liste des commandes implémentées.

Commande Description

help

Affiche l'ensemble des commandes disponibles dans le Shell

logo

Affiche le logo en mode texte

music

Joue la musique de tetris

echo

Active ou désactive l'echo des touches à l'écran

kill X

Tue le processus de PID X

chprio X Y

Change la priorité du processus X et lui donne la priorité Y

ps

Affiche la liste de tous les processus du système

exit

Reboot le système

sysinfo

Affiche l'ensemble des informations relatives aux files de messages

./proc

Lance le processus proc

./proc &

Lance le processus proc en tâche de fond

./autotest

Lance les test fournis de la partie user

Phase d'extensions

Une fois arrivé ici, on a rempli tous les objectifs demandés par le sujet. On est alors libre de choisir des extensions à notre projet. Nous en avons choisi quelques unes qui nous semblaient intéressantes :

  • Gestion du son
    • Bip lorsque le buffer clavier est plein : fonction qui effectue un bip sonore
    • Musique jouable : fonction qui effectue un son en fonction de la fréquence donnée
  • Gestion des leds du clavier : éclairage cohérent avec l'état du clavier
  • Amélioration du shell
    • Affichage des commandes possibles (<tab> <tab>)
    • Ctrl+c pour tuer le processus courant : affiche un message d'erreur si le kill echoue
    • Ctrl+l pour effacer l'écran
    • Prompt non effaçable
  • Souris
    • Défilement de l'historique du shell grâce à la molette de la souris

Principales difficultés

Il y a deux principaux problèmes :

  • Déboguer
  • Comprendre ce qui est demandé

Déboguer

Il faut se rendre compte que pour déboguer le programme, nous n'avons pas accès aux même outils que lors d'autres projets. Principalement, on se sert de traces écrites. Il faut donc pour cela réussir à implémenter l'affichage à l'écran. Heureusement, cela est assez rapidement fait, (d'autant plus si l'on a déjà fait les tp de PSE). Mais nous avons appris d'autres techniques pour trouver les problèmes dans notre noyau. Nous allons lister ici les principales :

  • Trace écrite avec printf : pour voir jusqu'à où le programme va sans planter, les valeurs de certaines variables, ...
  • Boucle infini en assembleur (boucle : jmp boucle) : permet de savoir a quel instruction assembleur l'ensemble crash
  • GDB avec affichage des lignes (layout (asm)) : on peut suivre pas à pas chaque instruction C ou assembleur
  • Lire les messages d'erreur lors d'un crash (écran bleu) : beaucoup d'informations sont affichées (valeur des registres, des pointeurs de piles, ...)
  • objdump : Permet de décompiler le binaire kernel.bin pour savoir quelle instruction assembleur et quelle fonction fait planter

Compréhension du sujet

Certaines parties sont très vastes, et difficile à prendre en main même avec toute la documentation disponible. Il faut alors ne pas hésiter à poser des questions aux encadrant ou aux autres équipes. La partie sur la mémoire virtuelle par exemple est un gros bloc qu'il faut implémenter d'une traite. Il donc difficile d'en comprendre tous les enjeux et nécessités dès le début. Il faut tout de même essayer de comprendre l'ensemble pour ne pas faire fausse route. De même, il y a beaucoup de documentation sur le wiki, mais elle n'est pas toujours rassemblée au même endroit, ce qui ne facilite pas la tâche pour implémenter certaines fonctionnalités, en particulier celles de la partie 5, où presque tout est expliqué, mais est éparpillé entre pages wikis et PDFs.
Pour la suite, lors de la phase d'extension, il n'y a presque pas d'information sur le wiki. Il faut donc aller voir ailleurs. De nombreux site explique comment coder un système d'exploitation, mais il faut faire attention à la valeur qu'ont ces informations (même matériel? même implémentation?). Il faut donc garder un œil critique sur du code que l'on trouve sur internet.

Bibliographie

Nous nous sommes très fortement appuyé sur le wiki qui contient toutes les informations nécessaires aux premières phases.
http://ensiwiki.ensimag.fr/index.php/Projet_syst%C3%A8me#Documentation_du_projet
Le détails des exceptions intel (obligatoire pour décrypter les erreurs intel) :
http://wiki.osdev.org/Exceptions
Pour la gestion des sons et de la musique :
http://wiki.osdev.org/PC_Speaker
http://fr.openclassrooms.com/forum/sujet/delire-de-geek-faites-chanter-votre-pc-39942
De manière générale :
http://wiki.osdev.org/ (source d'informations énorme)
Pour des questions que d'autres se sont posées avant nous : http://stackoverflow.com

Equipe

Aubert Bastien : filière ISI

Pesez Stéphane : filière ISI

Vinchon Arthur : filière ISI