Projet système PC : 2019 - BALLEYDIER Loic, PIERRET Arnaud : Différence entre versions

De Ensiwiki
Aller à : navigation, rechercher
Ligne 100 : Ligne 100 :
 
# FILES= crt0.S syscall.S start.c mem.c test.c printf.c sprintf.c doprnt.c panic.c string.c
 
# FILES= crt0.S syscall.S start.c mem.c test.c printf.c sprintf.c doprnt.c panic.c string.c
 
DIRS=. ../shared
 
DIRS=. ../shared
<pre>
+
</pre>
  
 
=== Phase d'extension ===
 
=== Phase d'extension ===

Version du 25 juin 2019 à 14:50

ArcheOS small.png
Titre du projet ArcheOS
Cadre Projet système

Équipe Loic Balleydier, Arnaud PIERRET
Encadrants Yves Denneulin , Gregory Mounie, Patrick Reignier


Présentation

ArcheOS.png

L'objectif de ce projet est la réalisation d'un noyau de système d'exploitation à partir d'une base fournie par les enseingants

Equipe

Organisation

Pour la majorité du projet, devant la complexité de celui-ci, nous avons décidé de développer en peer-programming afin de pouvoir mieux assimiler ensemble les différents aspects du projet. En revanche, à partir de la fin de la phase 5, nous nous sommes divisé le travail, l'un travaillant sur la phase 6 et l'autre sur la phase 7, avant de se rejoindre sur la phase 7 pour implémenter les diverses fonctionnalités de notre shell.

Phases de développement

Phase 1 : prise en main de l'environnement

100 %

Cette première phase ne pose pas de difficulté particulière.

N'hésitez pas à reprendre le code que vous avez déjà écrit l'année dernière en Langage de Base mais passez du temps a bien le comprendre de nouveau (si vous ne l'aviez pas bien commenté). Tout n'est pas nécessaire, pensez donc à élaguer le code inutile.

Concernant l'environnement, prenez du temps pour comprendre comment lancer GDB et l'utiliser (pour notre part, nous ne l'avons pas fait et nous avons réussi à ne pas l'utiliser jusqu'à la phase 5 où il a été impossible de continuer sans, donc ce n'est pas du temps perdu). Vous pouvez remplacer votre ~/.gdbinit par celui proposé ici qui permet d'avoir une interface plus agréable mais surtout d'afficher tout un tas d'informations utiles lors du débogage.

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

100 %

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

100 %

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

100 %

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

100 %

Si vous avez déjà lu les wikis d'autres groupes, vous devez déjà savoir que cette phase est compliqué, complexe, critique, et j'oublie sûrement d'autres adjectifs... Cette phrase demande beaucoup de patience, de réflexion et de tests. Lire énormément de ressources ne vous aidera pas forcément à tout comprendre et peux même vous perdre plus qu'autres choses. Si nous devions refaire cette partie à postériori, voici comment nous nous y prendrions:

La première chose à tester est de réussir à passer côté user lors du lancement du processus. Cela peut ce faire uniquement en simulant un retour d'interruption.

  • La pile kernel jusqu'à maintenant unique va être remplacée par 2 piles:
    • La pile kernel qui était déjà présente et qui va complètement changer de contenu. Elle a une taille fixe que vous fixerez qui est assez importante pour effectuer les différentes fonctions que vous avez développé en phase 2, 3 et 4. Elle contient 5 valeurs qui vont être dépilées par l'instruction assembleur iret utilisé pour simuler le retour d'interruption. Vous devrez empiler dans l'ordre:
      • SS (Stack Segment) qui indique que les éléments de la stack après le retour d'interruption seront des éléments appartenant à une stack user. SS est égale à 0x4b en mode user et 0x18 en mode kernel.
      • Le sommet de la pile user (l'adresse de la dernière adresse empilée sur la pile user) pour qu'elle soit stockée dans %esp.
      • EFLAG qui vaut 0x202 en mode user
      • CS (Code Segment) qui comme SS indique que vous allez utilisé du code en mode user. CS est égale à 0x43 en mode user et 0x10 en mode kernel.
      • Le pointeur de la fonction à lancer
      • Une dernière valeur est à empiler sur la pile kernel et correspond à la fonction assembleur permettant de démarrer votre processus en mode user par retour d'interruption.
    • La pile user qui va sensiblement être identique à votre ancienne pile kernel. Sa taille comprend la taille demandé par l'utilisateur ainsi que des octets supplémentaires servant à empiler ce qui suit (cette taille augmentera progressivement lors de vos tests afin de ne pas faire de stack overflow lors des appels systèmes):
      • L'argument de la fonction à lancer en mode user
      • La fonction de retour que vous avez développé dans les phases précédentes.
      • /!\ Vous ne devez plus empiler le pointeur de la fonction à lancer dans la pile user car il est déjà présent dans la pile kernel
  • Une fois les piles en place, il faut développé la fonction permettant de faire le changement de privilège par retour d'interruption. Ce code est tout simple et contient uniquement le changement de valeur des registres %ds, %es, %fs, %gs qui vont prendre la même valeur que le registre SS suivi d'un iret.

Afin de tester que vous arrivez bien à passer en mode user, vous pouvez lancer gdb et placer un breakpoint dans votre fonction assembleur permettant d'opérer le changement de privilège. Juste avant de faire votre iret, vous pouvez tester que votre pile kernel est correctement initialisée (la fonction user_start se trouve à l'adresse 0x1000000). Avant de faire votre iret dans GDB, vous devez charger le fichier de symbole de la partie user pour pouvoir afficher le code assembleur côté user. Pour cela vous devez taper: add-symbol-file ../user/user.debug 0x1000000. Vous devez normalement arriver en mode user après ceci.

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

100 %

Après la phase 5, cette phase semble déjà beaucoup plus abordable. Nous nous sommes inspirés d'un TP réalisé en Logiciel de Base pour récupérer les concepts nécessaires pour la mise en place de l'interruption 33.

Pour les buffers du clavier, nous avons utilisée la file (queue.h) afin de réaliser plusieurs cons_read. Notre première idée était d'utiliser un buffer unique, mais il fallu changer en cours de route car cette implémentation ne permet pas de faire passer le test 19.

Certains aspects n'ont pas été gérés, notamment le caractère au code 8 (BS).

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

90 %

Pour cette phase, nous avons implémenté les fonctions suivantes (extrait de la commande help):

  • ps : Display processes in the system
  • echo : Enable/disable echo of the terminal
  • clear : Clear the terminal
  • date : Display the current date
  • uptime : Display how long the system has been up
  • test : Launch the test interface
  • sys_info : Display some system information
  • sleep : Sleep the terminal
  • exit : Reboot the system
  • help : Display this help screen
  • logo : Display the logo

Attention : Si vous avez besoin de créer des nouveaux fichier dans la partie shared, il ne faut pas oublier de les préciser dans le Makefile de user. Par exemple, si vous ajoutez un fichier console.c dans shared, il vous faudra le rajouter ici :

# Files to compile
FILES= crt0.S fct_syscall.S $(wildcard *.c) printf.c sprintf.c doprnt.c panic.c string.c console.c
# FILES= crt0.S syscall.S start.c mem.c test.c printf.c sprintf.c doprnt.c panic.c string.c
DIRS=. ../shared

Phase d'extension

0 %

Journal de bord

05/06/2019 - Mise en place de l'environnement

  • Mise en place de l'environnement de développement
  • Reprise du code de Logiciel de Base afin de pouvoir écrire dans la console
  • Lecture de la Phase 2 et début de mise en place de la structure de donnée pour les processus
  • Tentative de création et communication entre deux processus (WIP)

06/06/2019 - Mise en place de la communication entre processus

  • Création et communication entre 2 processus via l'appel du context switch manuellement
  • Prise en main de la queue (pour exploitation ultérieure)
  • Implémentation de l'interruption lié au signal d'horloge
  • Appel automatique du context switch via le signal d'horloge

07/06/2019 - Début de l'ordonnancement

  • Traitement du signal d'horloge en fonction d'une fréquence différente à celle de l'horloge (SCHED_FREQ)
  • Implémentation des fonctions permettant de récupérer le pid et la priorité ainsi que changer cette dernière
  • Mise en place d'une file (FIFO) gérant la priorité pour les processus

11/06/2019 - Début de gestion de la filiation

  • Création d'une liste chaînée pour stocker les processus fils d'un parent
  • Mise en place de la fonction exit() pour pouvoir quitter un processus
  • Correction de l'utilisation des adresses de la pile pour pouvoir utiliser les arguments de fonction
  • Tentative de l'implémentation de la fonction waitpid (WIP)

12/06/2019 - Fin de gestion de la filiation

  • Waitpid est terminé
  • Terminaison des processus par kill
  • Support de l'instruction return pour récupérer la valeur
  • Support de l'endormissement des processus
  • Modification de la structure d'ordonnancement
  • Amélioration de la gestion de la mémoire pour les processus terminés

13/06/2019 - Journée de test

  • Tentative de lancement des tests côté kernel jusqu'à 10h
  • Bug fix le reste de la journée

14/06/2019 - Bugfixes et files de messages

  • Fin des bugs fix pour faire passer les 8 premiers tests de test.c
  • Début de mise en place des files de message
  • Réussite des tests 9,10,12,14

17/06/2019 - Fin de la phase 4

  • Fin de la mise en place des files de message (Fin de la phase 4)
  • Changement de structure pour les files de messages afin de respecter mot-à-mots les specifications
  • Compréhension et prise en main de la phase 5

18/06/2019 - Phase 5: Début

  • Réflexion sur la phase 5
  • Tentative de création de processus en mode kernel avec programme de boot

19/06/2019 - Phase 5: Suite

  • Début de l'implémentation du passage du mode kernel au mode user.
  • Bug fix, réussite du test 17

20/06/2019 - Phase 5: Suite 2

  • Bug fix, réussite des tests 11 et 20.
  • Mise en place du passage Ring0 <-> Ring3
  • Ecriture des appels systèmes

21/06/2019 - Fin de la phase 5

  • Debug des tests côté user (tous sauf le 19)
  • Fin de la phase 5
  • Début de l’implémentation du clavier

24/06/2019 - Phase 6 et 7

  • Mise en place de la gestion du clavier
  • Passage du test 19
  • Création d'un shell
  • Début d'écriture de nouveaux appels systèmes (ps)

24/06/2019 - Phase 7

  • Suite de l'écriture des appels systèmes (sys_info,logo,uptime,...)

Ressources externes

Pour gérer la liste des fils, nous avons utilisé une liste chainée simple crée par Troy D. Hanson, en licence BSD, opensource. Nous l'avons choisi grâce au conseil d'un groupe de l'année dernière