Projet système PC : 2017 - Julien Basson, Vincent Bonnecuelle, Jibril Saffi

De Ensiwiki
Aller à : navigation, rechercher
Awos logo.png
Titre du projet AWOS
Cadre Ensimag

Équipe Julien Basson Vincent Bonnecuelle Jibril Saffi
Encadrants François Broquedis , Gregory Mounie, Patrick Reignier


Introduction

Ce projet a pour objet la création d'un noyau de système d'exploitation sur une architecture Intel 80386 (abrégée i386).

Les principales connaissances académiques mises en jeu sont celles acquises lors du cours de SEPC, elles seront ici appliquées — et approfondies — lors de la réalisation du projet en question. Ladite réalisation est décomposée en plusieurs phases distinctes décrites ici sous forme de roadmap. Hormis ce cahier des charges imposé, notre ouvrage prend compte de l'ensemble des étapes propres à un cycle de développement logiciel « classique ». À ce titre, notre méthodologie s'inspire grandement des méthodes agiles et vise plus spécifiquement à respecter les principes dépeints par l'extreme programming (XP) : programmation en binôme, intégration continue, développement piloté par les tests (TDD), convention de nommage, etc.

Plan de développement

Phase 1

Phase 1 Prise en main de l'environnement
100 %
Concepts clés Commentaires

Outils utilisés

Compilation des sources avec gcc, émulation de l'hôte avec qemu et débogage avec gdb. Il est important de noter que la version de gcc diffère selon le type de machine utilisée : version 4 sur les machines de l'école contre la version 7 sur nos machines personnelles. Or la version 7 nécessite l'ajout d'un flag, présent uniquement depuis cette version et qui permet la bonne compilation des sources. Compte-tenu que certains membres du groupe travaillent sur les machines de l'Ensimag et d'autre sur leurs propres machines, il est nécessaire que la commande make vérifie au préalable la version de gcc utilisée pour ajouter ou omettre ce fameux flag.

Configuration des outils

Ajout de deux règles supplémentaires dans le Makefile :

  • make debug : lancer une session de débogage avec gdb liée à la machine virtuelle qemu
  • make qemu : lancer le programme principal dans une machine virtuelle qemu

Définition d'un style de programmation, très proche du coding style mis en œuvre dans le Kernel Linux.

Primitive d'affichage

Implémentation d'une fonction console_putbytes permettant l'affichage des caractères, en tenant compte de la gestion du curseur et du défilement. Cette dernière est très similaire à une fonction assembleur réalisée antérieurement lors d'un TP de logiciel de base, à un point tel que nous avons pu réutiliser une partie du code existant.

Phase 2

Phase 2 Création et lancement de processus de niveau noyau
100 %
Concepts clés Commentaires

Notion de processus

Modélisation des données des processus (identification, état, priorité, parent, enfants) et prise en main de mem_alloc. Ces mêmes processus seront ensuite lancés avec la fonction start qui exécutera donc un programme présent en mémoire.

Système à temps partagé

Implémentation de la fonction de changement de contexte et d'un traitant d'interruption pour l'horloge.

Phase 3

Phase 3 Ordonnancement, création dynamique et terminaison de processus de niveau noyau
100 %
Concepts clés Commentaires

Ordonnancement

Utilisation des macro fournies dans queue.h, ajout d'une structure de processus Activable contenant un pid et une priorité. Création de fonction permettant de sélectionner le prochain processus select_next_pid, ainsi qu'une autre permettant de changer de contexte vers un processus de pid donné.

Filiation

Ajout de la liste des fils d'un processus dans la structure d'un processus. Maintiens également de la valeur de retour si demandée par le père. waitpid retourne donc la valeur de sortie d'un des fils.

Terminaison

Implémentations des fonctions de terminaisons d'un processus _exit, kill et return. La fonction kill permet de tuer n'importe quel processus vivant (sauf 0). La fonction _exit sort d'un processus et fixe la valeur de retour. La fonction pour return est exit_by_return, celle-ci est la fonction placé dans la pile d'un processus lors de son initialisation, elle est chargé de récupérer la valeur du registre eax du processeur.

Cycle de vie

Développement des fonctions getpid, getprio et chprio.

Phase 4

Phase 4 Gestion des communications et synchronisation de processus de niveau noyau
100 %
Concepts clés Commentaires

Les files de messages

Création d'une structure de file de messages (Queue). Celle-ci est composée de Message, de Reader et de Writer. Une Queue contient également un numéro de tour permettant à un processus de savoir si la file à été supprimée ou réinitialisée pendant qu'il était en attente.

wait_clock

Mise en pause d'un processus pour un nombre de cycle d'horloge. Les cycles écoulés sont comptés dans l'horloge et la date de réveil est enregistrée dans la structure du processus.


Phase 5

Phase 5 Séparation des espaces mémoires du noyau, ajout du mode utilisateur pour les processus.
100 %
Concepts clés Commentaires

Séparation mémoire

Modification de la structure d'un processus, ajout d'une pile utilisateur de taille demandée lors du démarrage d'un processus. Conservation de l'ancienne pile kernel pour l’exécution des appels systèmes.

Mode utilisateur

Modification du changement de contexte d'un processus, sauvegarde de la pile kernel dans la TSS et ajout d'une fonction appelé lors d'un changement de contexte mettant en place les registres aux valeurs nécessaires pour le mode utilisateur. Restauration du niveau kernel par l'interruption 49 avec un passage de paramètre par les registres processeur.

Phase 6

Phase 6 Création d'un pilote de console (entrée / sortie)
100 %
Concepts clés Commentaires

Sortie écran

Implémentation de cons_write par un appel système vers la fonction kcons_write du kernel utilisée depuis le début du projet par printf.

Entrée clavier

Lecture au clavier grâce à l'écriture d'un traitant pour l'interruption 33. Sauvegarde des caractères dans un tampon de taille fixe.

Phase 7

Phase 7 Développement d'un interprète de commande (shell)
100 %
Concepts clés Commentaires

Interprète de commande

Développement des commandes :

  • ps - affichage des processus
  • echo - affichage de l'écho du clavier
  • exit - arrêt du shell
  • help - affiche la liste des commandes
  • kill - meurtre d'un processus
  • print - affichage d'un message à l'écran
  • random - générer un nombre aléatoire (ne fonctionne pas sur qemu)
  • colors - changer la couleur du texte
  • sleep - mise en pause du processus
  • uptime - durée depuis laquelle le système est lancé
  • test - exécution des tests sur le mode user

Phase d'extension

Phase d'extension Développement d'un système de fichier: FAT 16
20 %
Concepts clés Commentaires

Recherche sur FAT 16

Documentation sur les sites suivants :

Implémentation de FAT 16

Création de la FAT (File Allocation Table) et de fonctions permettant de récupérer les clusters d'un fichier, d'en allouer de nouveaux et d'en supprimer.

Création d'un file descriptor (fermeture, écriture et lecture dans un secteur déjà alloué).

Début de la création d'un fichier à partir d'un path.

Journal de bord

  • 08/06/2017
    • feuilletage de la documentation ;
    • compilation du code source fourni sur nos machines personnelles ;
    • ajout de deux nouvelles règles dans le Makefile ;
    • ajout d'une primitive d'affichage afin de réaliser des tests préliminaires ;
    • amorçage de la phase 2 avec la définition d'une structure représentant un processus ;
    • implémentation de la fonction start permettant de lancer ledit processus.
  • 09/06/2017
    • implémentation de la fonction context_switch permettant aux processus de se passer la main tour à tour ;
    • mise en place d'un traitant d'interruption pour utiliser l'horloge matérielle comme source d’interruption ;
    • fin de la phase 2 avec l'implémentation de la fonction ps_clk_process_switch permettant le changer de processus selon la valeur renvoyée par le timer ;
    • amorçage de la phase 3 avec le prototypage du scheduler, gestionnaire chargé de gérer l'ordonnancement des processus ;
    • définition de la wait_list : une structure de données de type liste chainée visant à stocker les processus à l'état « READY » ;
  • 12/06/2017
    • remplacement de la wait_list par la structure queue déjà fournie ;
    • implémentation des différentes fonctions définies dans le scheduler : scheduler_add, scheduler_remove, process_switch, etc. ;
    • implémentation de la fonction wait_clock : un processus à l'état « ACTIVE » est mis dans la liste asleep ;
    • implémentation de la fonction wake : un processus situé dans la liste asleep est mis à l'état « READY ».
  • 13/06/2017
    • implémentation de la fonction kill : tue le processus associé au pid donné en argument ;
    • implémentation de la fonction _exit : tue le processus actif ;
    • implémentation de la fonction exit_by_return : le processus se termine normalement et va chercher dans %eax la valeur de retour pour la transmettre a son père ;
    • implémentation de la fonction waitpid : attente et récupération de la valeur de retour d'un fils terminé ;
    • amorçage de la phase 4 avec le prototypage des files de messages (message_queue).
  • 14/06/2017
    • implémentation de la partie consommateur (reader) dans la message_queue ;
    • nombreux correctifs mineurs pour valider les premiers tests unitaires ;
    • tests unitaires validés (mode kernel) : 1 et 2.
  • 15/06/2017
    • correctifs mineurs sur la fonction wait_pid ;
    • implémentation de la production des messages (writer) dans la message_queue ;
    • tests unitaires validés (mode kernel) : 3, 4 et 5.
  • 16/06/2017
    • correction de la sortie des processus (nettoyage des enfants et changement de contexte) ;
    • problèmes de mémoire sur test 6, résolu par la suppression du flags gstabs dans le Makefile du kernel ;
    • tests unitaires validés (mode kernel) : 6 et 7.
  • 19/06/2017
    • correction de la réception : récupère un message en attente si file presque pleine ;
    • correction de l'émission : donne directement un message si file presque vide ;
    • tests unitaires validés : 8, 9, 10, 12 et 13.
  • 20/06/2017
    • correction de la mort des fils : rendu au père dans l'ordre FIFO, first out = first dead ;
    • correction du reset d'une file : changement du réveil des processus (pas immédiat)
    • ajout d'une vérification de la mémoire totale allouée aux processus
    • tests unitaires validés (mode kernel) : 14, 15, 16, 17 et 20.
  • 21/06/2017
    • début de la phase 5
    • ajout d'une pile utilisateur
    • modification du contexte switch descente vers le ring 3 (mode utilisateur)
    • ajout d'un prefix devant tous les appels systèmes du kernel kcons_write, k...
  • 22/06/2017
    • ajout d'une interruption pour les appels systèmes, restauration des registres de niveau kernel
    • la fonction de retour est placée à une adresse fixe pour être accessible par le kernel et par l'utilisateur
  • 23/06/2017
    • correction de l'adresse sauvegardé dans esp0, pointe sur la fin de l'espace allouée au kernel
    • nettoyage des files lors de la mort d'un processus
    • réalisation de la phase 6
    • implémentation de la lecture console
    • tests unitaires validés (mode utilisateur) : 1 à 20.
  • 26/06/2017
    • réalisation de la phase 7
    • ajout de diverses commandes
    • recherches sur le système de fichier FAT 16
  • 27/06/2017
    • ajout de diverses commandes (help...)
    • début d'implémentation du système de fichiers FAT 16
    • impossible de terminer le système de fichiers par manque de temps