Projet système PC : 2019 - JULIEN Tristan, LANUSSE Quentin : Différence entre versions

De Ensiwiki
Aller à : navigation, rechercher
(Présentation)
(Phases de développement)
 
(56 révisions intermédiaires par 2 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
 +
{{Projet Étudiant
 +
|cadre=Projet système
 +
|titre=BambinOSS
 +
|image=[[Fichier:BambinOS_logo.png|300px]]
 +
|equipe=[mailto:quentin.lanusse@grenoble-inp.org Quentin LANUSSE], [mailto:tristan.julien@grenoble-inp.org Tristan JULIEN]
 +
|encadrants=[mailto:Gregory.Mounie@imag.fr Gregory Mounie], [mailto:Patrick.Reignier@imag.fr Patrick Reignier], [mailto:yves.denneulin@univ-grenoble-alpes.fr Yves Denneulin]}}
 +
 
[[Catégorie:Projets de spécialité]]
 
[[Catégorie:Projets de spécialité]]
 
==Présentation==
 
==Présentation==
Ligne 14 : Ligne 21 :
 
:*[mailto:quentin.lanusse@grenoble-inp.org Quentin Lanusse] (filière [http://ensimag.grenoble-inp.fr/fr/formation/ingenieur-par-apprentissage#page-presentation apprentissage])
 
:*[mailto:quentin.lanusse@grenoble-inp.org Quentin Lanusse] (filière [http://ensimag.grenoble-inp.fr/fr/formation/ingenieur-par-apprentissage#page-presentation apprentissage])
  
==Planning==
+
==Gestion de projet==
 +
 
 +
===Organisation===
 +
Nous avons décidé de faire l'intégralité du projet en pair programming afin que chacun de nous puisse bien comprendre tout ce que nous avons fait. Avec le recul, si cela nous a peut-être légèrement ralenti nous ne pensons pas que nous aurions pu aller beaucoup plus loin même avec une répartition des tâches. Nous avons également pris grand soin d'équilibrer le temps de codage et le nombre de commits de chacun, grâce à cela, nous avons tous les deux une excellent compréhension de chaque fonctionnalité notre OS.
  
 
===Planning prévisionnel===
 
===Planning prévisionnel===
 +
::[[Fichier:BambinOSS_planPrev.png]]
  
 
===Planning effectif===
 
===Planning effectif===
 +
::[[Fichier:BambinOSS_planDef.png]]
  
 
==Phases de développement==
 
==Phases de développement==
Ligne 24 : Ligne 36 :
 
=== Phase 1 : prise en main de l'environnement ===
 
=== Phase 1 : prise en main de l'environnement ===
 
{{Avancement | 100}}
 
{{Avancement | 100}}
 +
Phase de prise en main du projet et de reprise des codes créés en assembleur l'an dernier.
  
 
=== Phase 2 : Création et lancement de processus de niveau noyau ===
 
=== Phase 2 : Création et lancement de processus de niveau noyau ===
{{Avancement | 5}}
+
{{Avancement | 100}}
 +
Phase importante qui correspond au vrai début du projet, les principaux points sont :
 +
* La création d'une première structure de processus.
 +
* La récupération et la gestion du timer du module 'Logiciel de Base' afin de traiter les interruptions d'horloge (#32).
 +
* Le changement de contexte pour passer d'un processus à l'autre.
  
 
=== Phase 3 : Ordonnancement, création dynamique et terminaison de processus de niveau noyau ===
 
=== Phase 3 : Ordonnancement, création dynamique et terminaison de processus de niveau noyau ===
{{Avancement | 0}}
+
{{Avancement | 100}}
 +
L'implémentation de la phase 3 a été plutôt rapide mais il a ensuite fallu déboguer les tests de cas difficiles, c'est ce qui nous a pris le plus longtemps, à la fin de cette phase les 9 premiers tests (à l'exception du 7) doivent passer.
 +
On détaille un peu plus bas comment faire les tests côté kernel.
 +
 
 +
Pour la gestion de l'endormissement, nous avons fait le choix de faire une queue de processus endormis, ce qui peut dans certains cas "casser" le côté FIFO de notre ordonnancement. Cela nous permet cependant d'avoir un code qui nous paraît plus clair et seulement des processus réellement activables dans notre queue de processus activables.
 +
 
 +
Pour passer le test 8 (test de performance), il nous a fallu bien vider les espaces mémoire alloués le plus tôt possible (dans kill, waitpid et exit) et ne faire une queue de processus morts à nettoyer que dans le cas particulier du exit. Cependant c'est peut-être lié uniquement à notre implémentation.
  
 
=== Phase 4 : Gestion des communications et synchronisation de processus de niveau noyau ===
 
=== Phase 4 : Gestion des communications et synchronisation de processus de niveau noyau ===
{{Avancement | 0}}
+
{{Avancement | 100}}
 +
Durant cette phase il faut faire attention à la documentation des primitives à implémenter, certains cas ne sont pas toujours simples à comprendre.
 +
 
 +
Nous avons choisi d'implémenter les files de messages comme des listes doublement chaînées ce qui nous semblait être le plus naturel à écrire.
 +
Nous avons également ajouté deux queues, une pour les processus en attente d'écriture et l'autre pour ceux en attente de lecture.
 +
 
 +
Attention wait_clock prend le nombre de clocks d'horloge à avoir atteint, pas le nombre à attendre... Si votre test 7 prend plus de 7-8s ce n'est pas normal.
  
 
=== Phase 5 : Séparation des espaces mémoire noyau et utilisateur : gestion de processus utilisateur ===
 
=== Phase 5 : Séparation des espaces mémoire noyau et utilisateur : gestion de processus utilisateur ===
{{Avancement | 0}}
+
{{Avancement | 30}}
 +
Courage... S'il vous reste moins de 2 jours ce n'est pas vraiment la peine de commencer sauf si vous êtes forts en espionnage industriel.
 +
Très flou, difficile de savoir par où commencer et comment déboguer, à priori une fois que l'on lance le mode user et que l'on arrive à implémenter une première primitive, ça se déroule assez simplement. Il faut cependant ensuite réussir à valider de nouveau les 20 tests, côté User cette fois-ci. Nous n'en sommes malheureusement pas arrivés là.
  
 
=== Phase 6 : Gestion du clavier et implémentation d'un pilote de console ===
 
=== Phase 6 : Gestion du clavier et implémentation d'un pilote de console ===
Ligne 45 : Ligne 76 :
 
==Journal de bord==
 
==Journal de bord==
 
=== Semaine 1 ===
 
=== Semaine 1 ===
====05-06-19====
+
====05 Juin 2019====
 
* Clonage du projet
 
* Clonage du projet
 
* Prise en main de l'environnement
 
* Prise en main de l'environnement
* Insertion du code de gestion d'affichage fait en Logiciel de Base dans le projet
+
* Intégration dans le projet du code de gestion d'affichage développé en Logiciel de Base en 1ère Année
* Début de création des processus
+
* Début de création d'une structure de processus
''Aujourd'hui, cela a été très difficile, il a fait très chaud et les vilains 1AA ont piqué la clim... :(<br>Heureusement qu'on avait les pauses frisbee''
+
 
 +
====06 Juin 2019====
 +
* Modification de la structure de processus
 +
* Début de lancement d'une fonction
 +
* Blocages sur la gestion des piles au sein des processus
 +
* Mise en place du ''context_switch()''
 +
* Découverte de l'environnement de debug
 +
 
 +
====07 Juin 2019====
 +
* Fonctionnement du ''context_switch()'' avec une table des processus statique
 +
* Début d'utilisation d'une queue des processus
 +
* Création du logo de BambinOS
 +
 
 +
<br>
 +
=== Semaine 2 ===
 +
====11 Juin 2019====
 +
* Modification et finalisation (pour la phase 2) de l'utilisation des processus avec une queue (queue de processus activables + pointeur vers le processus actif)
 +
* Gestion du timer
 +
* Gestion des interruptions pour changer de processus
 +
 
 +
::→ Fin de la Phase 2
 +
 
 +
====12 Juin 2019====
 +
* Gestion automatique des PIDs des processus
 +
* Gestion de l'endormissement d'un processus pour une durée déterminée : ''wait_clock'' (Phase 4)
 +
 
 +
====13 Juin 2019====
 +
* Fonctions de terminaison des processus : ''exit'', ''kill''
 +
* Primitives de gestion des processus : ''getprio'', ''chprio'', ''getpid''
 +
* Gestion de la filiation entre processus, et implémentation de ''waitpid''
 +
::→ Fin de la Phase 3
 +
 
 +
====14 Juin 2019====
 +
* Correction de code pour passage des premiers tests côté Kernel
 +
::→ Les tests 1 à 6 sont passés
 +
 
 +
<br>
 +
 
 +
=== Semaine 3 ===
 +
====17 Juin 2019====
 +
* Correction de code pour passage de nouveaux tests
 +
* Refacto du code pour passage du test 8 (début)
 +
 
 +
====18 Juin 2019====
 +
* Fin de refacto du code pour passage du test Kernel 8
 +
* Utilisation d'une fonction unique ''changer_etat()'' lors d'un changement d'état de processus.
 +
 
 +
* Implémentation de la base des files de messages, il faut maintenant finaliser leur mise en place pour passer les tests qui les concernent.
 +
::→ Les 10 premiers tests côté Kernel sont validés.
 +
 
 +
====19 Juin 2019====
 +
* Correction de l'implémentation des files de messages pour passage de tests
 +
::→ Les tests 10 à 14 côté Kernel sont validés.
 +
 
 +
====20 Juin 2019====
 +
* Mise en place de la libération d'espace alloué :
 +
** à des processus morts
 +
** à des files de messages supprimées
 +
* Correction de code pour passage des derniers tests Kernel (15 à 20)
 +
::→ Tous les tests côté Kernel sont à présent validés.
 +
 
 +
====21 Juin 2019====
 +
* Début de la phase 5 :
 +
** Lecture de documentation
 +
** Tentative de passage au mode user (ajout d'une pile user aux processus)
 +
::→ Difficile
 +
 
 +
<br>
 +
 
 +
=== Semaine 4 ===
 +
====24 Juin 2019====
 +
* Phase 5...
 +
** Passage des fonctions à lancer côté user et corrections d'autres erreurs de ce genre.
 +
::→ Difficile d'avancer sans visibilité, on ne sait pas directement si ce qu'on fait fonctionne ou non.
 +
 
 +
====25 Juin 2019====
 +
* Finalisation du projet :
 +
** Ajout de documentation de projet
 +
** Nettoyage et commentaires de code
 +
* Quelques avancées sur la mise en place d'un mode User :
 +
::→ l'OS entre bien en mode User, mais les appels systèmes utilisés ne sont pas tous implémentés par manque de temps.
 +
:: Il nous aurait donc fallu plus de temps pour avancer en debug et développer toutes les primitives nécessaires côté user.
 +
 
 +
<br>
  
 
==Démonstration==
 
==Démonstration==
  
 
==Difficultés rencontrées==
 
==Difficultés rencontrées==
 +
 +
===Les tests Kernel===
 +
Et non il ne suffit pas de copier-coller ''test.c'' dans ''kernel/'' pour que les tests soient exécutables. <br>Il faut récupérer la fin de ''user/crt0'' (les UNIMPLEMENTED) et les mettre à la fin de ''kernel/crt0'' (sauf ''console_putbytes'').
 +
Il faut également ajouter la primitive ''cons_write'' côté kernel si vous voulez l'affichage des printf des tests (elle se contente de faire un appel à ''console_putbytes'').
 +
 +
===Mode Debug - GDB===
 +
L'utilisation de GDB est inévitable tout au long du projet. Pour qu'il fonctionne, il faut bien penser à se placer dans le répertoire ''kernel'' (pour le debug côté Kernel) avant de lancer gdb, sinon il est incapable de trouver les fichiers sur lesquels vous voudrez définir des breaks. <br>
 +
Aussi, nous l'avons découvert trop tard, mais un module d'interface GDB peut s'avérer très pratique. On peut en trouver un ici : [https://github.com/cyrus-and/gdb-dashboard GDB Dashboard] (il suffit de placer le fichier ''.gdbinit'' dans son home).

Version actuelle en date du 25 juin 2019 à 14:45

BambinOS logo.png
Titre du projet BambinOSS
Cadre Projet système

Équipe Quentin LANUSSE, Tristan JULIEN
Encadrants Gregory Mounie, Patrick Reignier, Yves Denneulin

Présentation

L'objectif du projet système est la réalisation d'un noyau de système d'exploitation sur une architecture Intel x86 et, pour la première fois en 2019, le risc-v 64 bits. Les concepts principaux à mettre en oeuvre sont :

  • la création et l'exécution des processus ;
  • leur synchronisation ;
  • leur ordonnancement ;
  • la gestion des entrées/sorties (clavier, écran) ;
  • l'implémentation d'un interprète de commandes.

Equipe

Gestion de projet

Organisation

Nous avons décidé de faire l'intégralité du projet en pair programming afin que chacun de nous puisse bien comprendre tout ce que nous avons fait. Avec le recul, si cela nous a peut-être légèrement ralenti nous ne pensons pas que nous aurions pu aller beaucoup plus loin même avec une répartition des tâches. Nous avons également pris grand soin d'équilibrer le temps de codage et le nombre de commits de chacun, grâce à cela, nous avons tous les deux une excellent compréhension de chaque fonctionnalité notre OS.

Planning prévisionnel

BambinOSS planPrev.png

Planning effectif

BambinOSS planDef.png

Phases de développement

Phase 1 : prise en main de l'environnement

100 %

Phase de prise en main du projet et de reprise des codes créés en assembleur l'an dernier.

Phase 2 : Création et lancement de processus de niveau noyau

100 %

Phase importante qui correspond au vrai début du projet, les principaux points sont :

  • La création d'une première structure de processus.
  • La récupération et la gestion du timer du module 'Logiciel de Base' afin de traiter les interruptions d'horloge (#32).
  • Le changement de contexte pour passer d'un processus à l'autre.

Phase 3 : Ordonnancement, création dynamique et terminaison de processus de niveau noyau

100 %

L'implémentation de la phase 3 a été plutôt rapide mais il a ensuite fallu déboguer les tests de cas difficiles, c'est ce qui nous a pris le plus longtemps, à la fin de cette phase les 9 premiers tests (à l'exception du 7) doivent passer. On détaille un peu plus bas comment faire les tests côté kernel.

Pour la gestion de l'endormissement, nous avons fait le choix de faire une queue de processus endormis, ce qui peut dans certains cas "casser" le côté FIFO de notre ordonnancement. Cela nous permet cependant d'avoir un code qui nous paraît plus clair et seulement des processus réellement activables dans notre queue de processus activables.

Pour passer le test 8 (test de performance), il nous a fallu bien vider les espaces mémoire alloués le plus tôt possible (dans kill, waitpid et exit) et ne faire une queue de processus morts à nettoyer que dans le cas particulier du exit. Cependant c'est peut-être lié uniquement à notre implémentation.

Phase 4 : Gestion des communications et synchronisation de processus de niveau noyau

100 %

Durant cette phase il faut faire attention à la documentation des primitives à implémenter, certains cas ne sont pas toujours simples à comprendre.

Nous avons choisi d'implémenter les files de messages comme des listes doublement chaînées ce qui nous semblait être le plus naturel à écrire. Nous avons également ajouté deux queues, une pour les processus en attente d'écriture et l'autre pour ceux en attente de lecture.

Attention wait_clock prend le nombre de clocks d'horloge à avoir atteint, pas le nombre à attendre... Si votre test 7 prend plus de 7-8s ce n'est pas normal.

Phase 5 : Séparation des espaces mémoire noyau et utilisateur : gestion de processus utilisateur

30 %

Courage... S'il vous reste moins de 2 jours ce n'est pas vraiment la peine de commencer sauf si vous êtes forts en espionnage industriel. Très flou, difficile de savoir par où commencer et comment déboguer, à priori une fois que l'on lance le mode user et que l'on arrive à implémenter une première primitive, ça se déroule assez simplement. Il faut cependant ensuite réussir à valider de nouveau les 20 tests, côté User cette fois-ci. Nous n'en sommes malheureusement pas arrivés là.

Phase 6 : Gestion du clavier et implémentation d'un pilote de console

0 %

Phase 7 : Implémentation d'un interprète de commandes

0 %

Journal de bord

Semaine 1

05 Juin 2019

  • Clonage du projet
  • Prise en main de l'environnement
  • Intégration dans le projet du code de gestion d'affichage développé en Logiciel de Base en 1ère Année
  • Début de création d'une structure de processus

06 Juin 2019

  • Modification de la structure de processus
  • Début de lancement d'une fonction
  • Blocages sur la gestion des piles au sein des processus
  • Mise en place du context_switch()
  • Découverte de l'environnement de debug

07 Juin 2019

  • Fonctionnement du context_switch() avec une table des processus statique
  • Début d'utilisation d'une queue des processus
  • Création du logo de BambinOS


Semaine 2

11 Juin 2019

  • Modification et finalisation (pour la phase 2) de l'utilisation des processus avec une queue (queue de processus activables + pointeur vers le processus actif)
  • Gestion du timer
  • Gestion des interruptions pour changer de processus
→ Fin de la Phase 2

12 Juin 2019

  • Gestion automatique des PIDs des processus
  • Gestion de l'endormissement d'un processus pour une durée déterminée : wait_clock (Phase 4)

13 Juin 2019

  • Fonctions de terminaison des processus : exit, kill
  • Primitives de gestion des processus : getprio, chprio, getpid
  • Gestion de la filiation entre processus, et implémentation de waitpid
→ Fin de la Phase 3

14 Juin 2019

  • Correction de code pour passage des premiers tests côté Kernel
→ Les tests 1 à 6 sont passés


Semaine 3

17 Juin 2019

  • Correction de code pour passage de nouveaux tests
  • Refacto du code pour passage du test 8 (début)

18 Juin 2019

  • Fin de refacto du code pour passage du test Kernel 8
  • Utilisation d'une fonction unique changer_etat() lors d'un changement d'état de processus.
  • Implémentation de la base des files de messages, il faut maintenant finaliser leur mise en place pour passer les tests qui les concernent.
→ Les 10 premiers tests côté Kernel sont validés.

19 Juin 2019

  • Correction de l'implémentation des files de messages pour passage de tests
→ Les tests 10 à 14 côté Kernel sont validés.

20 Juin 2019

  • Mise en place de la libération d'espace alloué :
    • à des processus morts
    • à des files de messages supprimées
  • Correction de code pour passage des derniers tests Kernel (15 à 20)
→ Tous les tests côté Kernel sont à présent validés.

21 Juin 2019

  • Début de la phase 5 :
    • Lecture de documentation
    • Tentative de passage au mode user (ajout d'une pile user aux processus)
→ Difficile


Semaine 4

24 Juin 2019

  • Phase 5...
    • Passage des fonctions à lancer côté user et corrections d'autres erreurs de ce genre.
→ Difficile d'avancer sans visibilité, on ne sait pas directement si ce qu'on fait fonctionne ou non.

25 Juin 2019

  • Finalisation du projet :
    • Ajout de documentation de projet
    • Nettoyage et commentaires de code
  • Quelques avancées sur la mise en place d'un mode User :
→ l'OS entre bien en mode User, mais les appels systèmes utilisés ne sont pas tous implémentés par manque de temps.
Il nous aurait donc fallu plus de temps pour avancer en debug et développer toutes les primitives nécessaires côté user.


Démonstration

Difficultés rencontrées

Les tests Kernel

Et non il ne suffit pas de copier-coller test.c dans kernel/ pour que les tests soient exécutables.
Il faut récupérer la fin de user/crt0 (les UNIMPLEMENTED) et les mettre à la fin de kernel/crt0 (sauf console_putbytes). Il faut également ajouter la primitive cons_write côté kernel si vous voulez l'affichage des printf des tests (elle se contente de faire un appel à console_putbytes).

Mode Debug - GDB

L'utilisation de GDB est inévitable tout au long du projet. Pour qu'il fonctionne, il faut bien penser à se placer dans le répertoire kernel (pour le debug côté Kernel) avant de lancer gdb, sinon il est incapable de trouver les fichiers sur lesquels vous voudrez définir des breaks.
Aussi, nous l'avons découvert trop tard, mais un module d'interface GDB peut s'avérer très pratique. On peut en trouver un ici : GDB Dashboard (il suffit de placer le fichier .gdbinit dans son home).