Projet système PC : 2019 - BUSSER Nicolas, DELEVOYE Valentin, DORGUEIL Corentin, GINDRE Guillaume, MOUHAT COURVOISIER Louis, PICCINI Alexandre

De Ensiwiki
Aller à : navigation, rechercher

Présentation

Objectifs

Développement d'un noyau de système d'exploitation pour architecture x86:

  • création, exécution, terminaison de processus
  • synchronisation de processus
  • ordonnancement de processus
  • gestion de périphériques
  • interpréteur de commandes

Organisation de l'équipe

Nicolas BUSSER
Valentin DELEVOYE
Corentin DORGUEIL
Guillaume GINDRE
Louis MOUHAT COURVOISIER
Alexandre PICCINI

État du projet

Phase 1 - Gestion de l'affichage

100 %

Portage des sources du projet réalisé au premier semestre: (construction d'un petit noyau de système d'exploitation).

Phase 2 - Processus et changement de contexte

100 %

Implémentation de la structure de donnée représentant un processus.
Développement des fonctions de création de processus.
Implémentation des files de processus.
Gestion des interruptions timer.
Changement de contexte entre processus

Phase 3 - Ordonnancement et cycle de vie des processus

100 %

Implémentation du scheduler.
Gestion de la terminaison des processus.
Création dynamique des processus et gestion de leur filiation.

Phase 4 - Files de messages et endormissement des processus

100 %

Implémentation des primitives de gestion des files de messages.
Gestion de l'endormissement des processus.
Ajout de la primitive wait_clock.


Une difficulté notable a été la gestion des processus endormis sur file vide ou pleine lors:

  • d'une terminaison externe par appel des procédures exit ou kill
  • d'un changement de priorité demandé par le kernel

Phase 5 - Protection mémoire, appels système et protection d’exécution

75 %

Mémoire virtuelle

Choix: L'allocation des tables des pages s'effectue par le biais de la fonction fournie memalign (entre 1MiB et 64MiB). Évidemment, l'allocation des pages s'effectue via l'allocateur de mémoire physique réalisé par notre équipe.

Difficultés: Nous avons entamé la conception de la mémoire virtuelle uniquement à la sixième semaine. De plus, nous n'avions pas, à ce moment là, totalement terminé la partie 4. Ainsi, nous avons initialement chargé un des développeurs de l'architecture de tests de commencer à étudier l'implémentation de la mémoire virtuelle. Étant une partie compliquée et charnière au sein du projet, il semble, avec du recul, un peu léger de n'y avoir assigné qu'un développeur au départ. De plus, la partie 5 est assez touffue et requiert la maîtrise de concepts techniques comme les mécanismes de segmentation ou d'interruption. Ne pouvant réellement tester la mémoire virtuelle qu'une fois totalement implémentée, beaucoup d'erreurs de programmation se sont accumulées. Le site Osdev nous a beaucoup aidé à comprendre certaines étapes de l'implémentation.

Bilan Malgré toutes ces difficultés, les mécanismes de mémoire virtuelle ont été implémentés dans leur intégralité. La libération des page directory n'a néanmoins pas été testée en profondeur.

Appels système

Ils sont implémentés correctement mais pas parfaitement testés. Nous avons rencontré deux principales difficultés:

  • Les développeurs qui se sont penchés sur cet aspect du projet n'ont pas pris part à l'implémentation de la mémoire virtuelle et de la segmentation. L'équipe Mémoire virtuelle a du rapidement les briefer afin de faciliter la suite des opérations.
  • La compréhension de la documentation sur les appels systèmes ne fut pas simple. Nous avons trouvé une grande aide dans des sites externes parmis lesquels OsDev et Wikipédia.

Les liens suivants furent très instructifs:

Bilan: Le mécanisme d'appels systèmes est implémenté pour toutes les primitives systèmes de la spécification. Cependant, il ne fonctionne réellement que pour une partie d'entre elles.

Mode utilisateur

Le passage en mode utilisateur est implémenté correctement. Les limitations résident dans les appels systèmes qui ne fonctionnent pas systématiquement et les arguments qui ne sont pas pris en compte. Les difficultés du mode user ont été les suivantes:

  • Comprendre le mécanisme du premier passage en ring 3 et le mettre en application (éléments à empiler)
  • Posséder un mécanisme de mémoire virtuelle sans failles. Cela implique également de comprendre tous les concepts et d'être alerte vis-à-vis des flags de page

Phase 6 - Gestion des entrées clavier

65 %
  • Implémentation du pilote de clavier.

Pour réaliser cette partie il a fallu démasquer l'interruption clavier et créer le traitant associé. L'interruption fourni un scan code, qui doit être analysé pour obtenir le caractère associé à la touche enfoncée. Ces caractères sont stockés dans un buffer "keyboard_buf". On retient aussi l'indice courant d'écriture dans ce buffer. Lorsqu'un saut de ligne est détecté, on réalise alors un appel à cons_read, puis à l'interprète de commande, ce qui fait que l'interprète est actuellement une fonction côté kernel.

  • Implémentation de la console.

L'echo de la console permet à l'utilisateur de voir ce qu'il est en train de taper. La fonction cons_read prélève une ligne dans le buffer clavier. Normalement, si aucune ligne n'est disponible, cette fonction doit se bloquer. Comme la console est gérée comme une fonction kernel et non pas un processus, nous n'avons pas pu réaliser cette fonctionnalité, la fonction renvoie donc une "string" inchangée et une longueur nulle.

Bilan : Le pilote clavier, la console et l'interprète de commande se retrouvent liés et réalisés côté kernel car le blocage sur cons_read n'a pas été réalisé dans les temps.

Phase 7 - Interprète de commandes

40 %

Implémentation d'un shell.

Les entrées clavier étant traitées, on peut lancer des processus spécifiques à chaque fois qu'on appuie sur entrée, en fonction de ce qui a été tapé. La liste des commandes disponibles est la suivante:

  • ps: affiche la liste des processus courants
  • sinfo: affiche des informations sur les sémaphores
  • exit: quitte la fenètre (Non implémenté)
  • echo: active ou désactive l'option echo. Si elle est activée, les caractères tapés au clavier sont affichés à l'écran, sinon, ils ne le sont pas.
  • Bonus: start: permet de lancer un processus à la main, en lui fournissant le nom et les arguments de la fonction à lancer. Format: start <nom> <command_args>

Bilan: L'interprète de commande ne s'exécute pas comme un processus utilisateur. Il est resté intégré côté kernel car nous n'avons pas terminé la partie précédente (attente sur cons_read).

Aperçu du shell avec les fonctions ps et start.
Aperçu du shell

Extension

60 %

La lecture d'un son strident, faisant office de véritable millésime musical, a été implémentée sur la branche "sound". Nous n'avons cependant pas réussi à le tester proprement, et ne l'avons donc pas intégré dans le rendu final.

Architecture de tests

Les tests kernel fonctionnent de la manière suivante:

Tous les tests sont placés dans le dossier kernel/tests, et importé dans le fichier kernel/tests/test_launcher.c, qui est lancé par start.c lorsque la commande
make run
est appelée.

Lorsqu'elle cette commande est appelée, tous les tests qui se trouvent dans le tableau funcs seront exécutés.

Si vous voulez ajouter un nouveau test, il suffit donc de l'inclure dans le test_launcher.c, de le rajouter dans le tableau funcs. Attention, si vous mettez plus de 25 tests à la fois, les premiers résultats seront écrasés par les derniers.

Une fois tous les tests exécutés, la liste des tests, avec pour chacun s'il est réussi ou échoué, et si nécessaire un message d'explication, est affichée à l'écran.

Les résultats de différents tests.
Résultats des tests

Nous avons choisi d'effectuer tous les tests avant d'afficher leur résultats, par opposition à afficher les résultats des tests au fur et à mesure, car cela nous permettait de tester les fonctions d'affichage dans les tests sans brouiller les résultats. Ainsi, on peut effacer l'écran entre chaque test, et garder en mémoire un tableau contenant tous les résultats de tests.

Journal de bord

Première semaine: 4 Mars -> 8 Mars

  • Configuration de git
  • Manipulation du fichier queue.h
  • Analyse du MakeFile
  • Analyse de la spec

Deuxième semaine: 11 Mars -> 15 Mars

  • Equipe de dev:
    • Importation du code pcsef
    • Retouches du Makefile
  • Equipe de test:
    • Tâtonnements de conception de la structure de tests


Troisième semaine: 18 Mars -> 22 Mars

  • Equipe de dev:
    • Implémentation des primitives pcreate et pdelete
  • Equipe de test:
    • Création de l'architecture de tests
    • Création de tests pour screen.h

Quatrième semaine: 25 Mars -> 29 Mars

  • Equipe de dev:
    • Ecriture de primitives manquantes élémentaires de process.h (getprio, getpid, chprio)
    • Implémentation des primitives psend et preceiv
  • Equipe de test:
    • Retouche et amélioration de l'architecture de tests
    • Achèvement des tests de l'écran
    • Début de l'importation des tests users
    • Développement des tests basiques producteur/consommateur (files de messages)

Cinquième semaine: 1 Avril -> 5 Avril

  • Equipe de dev:
    • Implémentation des primitives pcount, preset et pcheckprio
    • Recherche et analyse de la phase 5
  • Equipe de test:
    • Modification majeure de l'architecture de test: les tests sont maintenant lancés un par un via la primitive start
    • Importation des tests user jusqu'à la phase 4
    • Identification et correction de bugs majeurs liés à la gestion des processus
    • Développement des tests avancés producteur/consommateur (files de messages)

Sixième semaine: 8 Avril -> 12 Avril

  • Equipe de dev:
    • Début de réalisation de la phase 5: réalisation d'un allocateur de mémoire virtuelle élémentaire
    • Implémentation de la primitive pcheckkill (files de messages), modification de la gestion des processus lors d'un SIGKILL
  • Equipe de test:
    • Développement des tests de changement de priorité dans les files de messages
    • Adaptation des tests des files de messages à l'architecture de test mise en place

Septième semaine: 15 Avril -> 19 Avril

  • Equipe de dev:
    • Fin de réalisation d'un prototype de mémoire virtuelle: arrivée en phase de debug
  • Equipe de test:
    • Deux personnes sont allés dans l'équipe de dev
    • Développement des tests SIGKILL dans les files de messages
    • Début de l'écriture des appels systèmes et du changement de mode

Huitième semaine: 29 Avril -> 3 Mai

  • Equipe de dev:
    • Début de réalisation des mécanismes de segmentation
    • Début de réalisation des interruptions de clavier

Neuvième semaine: 6 Mai -> 10 Mai

  • Equipe de dev:
    • Fin de la gestion du clavier
    • Début et fin de la gestion de la console
    • Début de la phase 7 : création du shell

Dixième semaine: 13 Mai -> 17 Mai

  • Equipe de dev:
    • Fin de l'écriture des appels systèmes et du changement de mode

Onzième semaine: 20 Mai -> 24 Mai

  • Equipe de dev
    • Tentatives de débogage des différents tests en user et des appels systèmes concernés
  • Equipe de test
    • Calibrage des tests en kernel