Projet Système PC : 2013 - Jean-Baptiste GASTINEAU, Jean-Yves NOLEN et Sergio VASQUEZ

De Ensiwiki
Aller à : navigation, rechercher


SergiOS

Développeurs Jean-Baptiste GASTINEAU
Jean-Yves NOLEN
Sergio VASQUEZ


Présentation du Projet

Ce projet système avait pour but de nous introduire à la programmation de systèmes d'exploitation, et de mettre en pratique les notions abordées dans ce même cours.

Nous avons implémenté en deux semaines et demi un noyau minimaliste de système d'exploitation mono cœur, multi-processus, avec gestion de l'écran et du clavier.

Ci dessous, nous décrivons les phases de l'avancement de notre travail, et toute autre indication utile à propos de l'implémentation de notre système nommé SergiOS en l'hommage de notre camarade.

Résumé du déroulement

Phase 1

Cette première phase est rapide et se déroule d'une façon très naturelle grâce aux divers supports du ensiwiki (e.g. Gestion d'écran) et au code pré-développé. Le but de cette phase est la prise en main de l’environnement de développement (i.e. QUEMU, code fourni, déboguer, etc.) et la gestion de l'écran. L'importance de cette étape est en particulier :

  • comprendre l’état du OS fourni – quasiment-nu –
  • enchaînement des fonctions pour faire du débogage – gdb et éventuellement des changements dans Makefile –
  • se donner un moyen de visualiser des messages – logs, asserts, retour fonctions –

Phase 2

Cette phase peut être divisée en 2 grandes parties

  • Tout d'abord la gestion des processus et plus particulièrement la notion de changement de contexte.
  • La gestion du temps au sein du noyau, permet temps d'obtenir un système de temps partagé par les processus en exécution.

Processus et Changement de contexte

Références: Changement de contexte, Processus

Afin de bien appréhender cette étape il est nécessaire de comprendre correctement la notion de changement de contexte, celui-ci consiste à sauvegarder l'état d'un processus avant de restaurer l'état du prochain processus à exécuter.

En pratique cela reviens à sauvegarder l'ensemble des registres ainsi que les registres de pile qui permettent de revenir à un état cohérent.

La difficulté principale est de bien comprendre le comportement de l’élément "Context Switch" notamment pour gérer le démarrage de processus.

En effet durant la première restauration d'un processus, celui ci n'a pas démarré et ne contient pas d'informations à propos de son exécution. On doit donc avant de lancer le context switch sur un nouveau processus initialiser la pile de ce dernier avec les bonnes valeurs, à savoir l'adresse de la fonction de démarrage, l'adresse de la fonction de terminaison (qui sera faite plus tard).

Gestion du temps

La gestion du temps dans notre système est faites par une horloge, le principe de l'horloge est de "sonner" à intervalle régulier, la gestion de ces sonneries est faites par interruption matérielle et nécessite un traitement préalable pour être activée.

Connaissant la fréquence de ces ticks (en Hz) il est facilement possible d'obtenir un système basé sur un temps observable de l'ordre de la seconde.

Nous avons pris le parti d'avoir une horloge sonnant à un rythme soutenu et lançant ordonnancement moins souvent, ainsi chaque processus obtient la main avec un quantum de temps raisonnable.

Pour pouvoir utiliser cette horloge, il faut la configurer cela revient à écrire des valeurs particulières à certains emplacements mémoires, il faut ensuite démasquer l'interruption n°32.

Phase 3

Durant cette phase on introduit la notion de filiation de processus.

Chaque processus (sauf idle, qui est un processus particulier, il est lui même son père) possède un père.

Pour gérer la filiation nous avons pris le parti que chaque processus possède une tête de liste vers les processus, et chaque processus un maillon de chaînage pour être présent dans une liste.

La gestion de l'ordonnanceur a été réalisé la encore par la mise en place de liste chaînée par priorité.

Nous possédons à la fin du projet, par processus : un maillon de chaînage pour la gestion des status des processus, un maillon pour la filiation, une tête de liste pour les trouver les fils. Au niveau noyau, une tête de liste pour chaque état de processus.

L'ordonnancement consiste à

  • Parcourir la liste des processus endormi pour vérifier si leur tick de réveil a été atteint
    • Dans ce cas on l'enlève le processus de la liste des endormis pour le rajouter à la liste des activables
  • Retirer l’élément de priorité maximale et le marquer comme processus élu
  • Le rajouter pour gérer le principe FIFO si plusieurs processus possède la priorité maximale
  • Effectuer le context switch entre le processus actif et l'élu (Néo entend moi !)

Phase 4

Références : les sémaphores Conduite du projet

Cette phase consiste à implémenter des sémaphores. Nous avons fait en sorte que la gestion des sémaphores soit isolée de la gestion des processus.

Nous avons donc implémenté toutes les fonctions de manipulation des sémaphore, sans toucher à notre table des processus directement, mais par appel à des fonctions systèmes propres à la gestion des processus.

Attention : il ne faut pas oublier de retirer un processus du sémaphore qui le bloquait quand il est tué par le kernel.

Phase 5

Celle-ci est la phase plus critique des 7 phases prévues pour ce projet système. Il ne faut pas se démotiver si les régression sont très importantes et si la documentation commence à être moins explicite et fournie que pour les phases précédentes (i.e. documentation mode user).

Cette étape est sensé d'apporter le mode user à OS dévélopper, et permettre des appel système pour commencer à protéger, abstraire et isoler les fonctions kernel déjà développées.

Mode Utilisateur

Les caractéristiques principales de cette mode sont :

  • utilisation des fonctions kernel via des interruption système
  • séparation du stack kernel pour faire du développement non polluant des fonctions kernel
  • dont les processus sont interruptibles et synchronisables


Sub-phases

Mise en place des appels systèmes

Le travail à fournir ici est très répétitif et la plupart en assembler. Les appels systèmes sont des interruptions (i.e. int $49) avec des paramètres. D'une part il faut faire un « emballage » en assembleur qui permet faire une interruption avec des arguments variables (i.e. variables en taille, type et nombre) et ainsi communiquer avec les fonctions kernel. D'autre part le traitant l'interruption (e.g. Comme celui de clock) qui fait les casts des paramètres fournis par l'interruption et fait les appels correspondant au fonctions kernel

Mise en place effectivement du changement entre modes

Préambule Bilan pharmaceutique : 3g de paracétamol en 1,5 jour, vous êtes avertis

Cette phase a été de mon points de vue (JY) la plus ardue, et celle qui m'a demandé le plus de temps à comprendre débugger.

Pour réaliser le changement de mode, il faut comprendre que chaque processus utilisateurs aura 2 piles

  • Une pile kernel
  • Une pile utilisateur

La partie ardue a été de comprendre l'initialisation de ces deux piles.

Pile Kernel

Pour la pile kernel il faut faire en sorte que les registres soit positionné avec les bonnes valeurs lors de l’exécution de l'instruction iret.

Pour cela il faut configurer esp pour que ce dernier pointe vers la pile user.

Il faudra également définir une fonction qui se chargement de positionner correctement les registres segments avant de faire un iret

Pile User

Dans la pile utilisateur il faudra positionner correctement l'argument de la méthode de démarrage et l'adresse de la fonction de terminaison.

Attention, cette dernier doit être une fonction de terminaison exécuté en mode user ;)

Phase 6

Références : Conduite de projet, le clavier, l'écran , aspects techniques

Cette phase consiste à gérer la console et à permettre une interaction de l'utilisateur avec le noyau. Deux modes sont possibles : le mode écho (par défaut) dans lequel tous les caractères frappés par l'utilisateur, et qui peuvent êtres stockés dans le tampon associé au clavier sont affichés, et l'autre mode dans lequel ils ne sont par affichés, mais enregistré dans le tampon quand même. Pour réussir cette phase, il faut autoriser (analogie avec l'horloge) les interruptions venant du clavier à interrompre le processus en cours, et créer un nouvel état bloquant dans la table des processus pour les processus en attente de caractères que l'utilisateur doit taper.

Phase 7 : Le Shell

Cette étape consiste en l'implémentation d'un shell, et repose sur la phase précédente : gestion de la console.

Nous avons implémenté plusieurs commmandes différentes :

  • ps : informations sur les processus en cours,
  • exit : éteindre le noyau.
  • sinfo : informations sur les sémaphores.
  • test : choisir le test à faire passer parmi les tests fournis par l'équipe encadrante.
  • ensitest : lancer tout le jeu de test.
  • wink : faire clignoter la console juste l'espace d'un instant.

Pour réaliser ces commandes, nous avons dû implémenter des appels systèmes supplémentaires, documentés dans nos API.

Résultats Atteints

Nous avons réussi dans le temps imparti à implémenter l'ensemble des éléments imposés par les spécifications.

Cependant la gestion de la console n'est pas complètement achevée, il reste quelques bug au niveau de la gestion du buffer.

Pistes d'améliorations

L'amélioration de notre Os est possible, nous n'avons pas eu le temps de réaliser des extensions, néanmoins la mise en place d'un système de fichier peut être une bonne chose.

La réalisation d'application user supplémentaire peut rendre le système plus interactif et convivial

Bilans personnels

Jean-Baptiste

Personnellement, ce projet m'a beau appris. Au départ j'avais pas mal d’appréhensions, mais j'étais vraiment très curieux. Je peux dire que j'ai touché de plus près à la programmation système et que j'ai acquis une meilleure maîtrise du langage C et de l'assembleur x86. Il nous est arrivé d'avoir des moments de blocage, et de consolidation du code (écrire nos propres tests) un peu ingrates, mais dans l'ensemble le travail était vraiment intéressant, et avançait régulièrement.

Jean-Yves

2,5 Semaines pour coder un OS ? Impossible me direz-vous ? Non !

Pour bien réaliser ce projet il faut tout d'abord éviter de ce lancer à corps perdu dans le code, prendre en main le code source fourni et comprendre effectivement ce qui ai demandé pour chaque phase.

Du points de vue personnel, ce projet m'a redonné goût au C, et m'a permis de mettre en application les cours de système des 3 derniers mois.

Cela permet également de se rendre compte du travail abattu par les contributeurs du noyau Linux, pour obtenir un noyau safe, et très robuste.

Sans nul doute, je me pencherai un peu plus sur les sources. Non pas pour comprendre l'ensemble mais pour apprécier l’architecture de ce dernier.

PS : Prévoir du paracétamol et du café, ça peut aider quand le mode user ne fonctionne pas ^_^

Sergio

Ce projet est très intéressant qui permet de consolider tous les connaissances apprises ou non des cours de systèmes.

Points positifs :

  • travail en équipe
  • confrontation au difficultés techniques lors du développement
  • compréhension des niveaux plus bas de toutes applications
  • mise en place d'une chaîne de production d'un OS quasiment à partir de rien

Points négatifs :

  • temps très limités
  • documentation ensiwiki difficilement exploitable pour les phases 5, 6 et 7
  • découverte du code fourni lors du projet et pas avant

Mon conseil:

L'apprentissage via la pratique est plus intéressante et les connaissances restent plus dans la tête.