Projet système PC : 2020 - REBOUL Julien, JODRY Etienne

De Ensiwiki
Aller à : navigation, rechercher
REBOUL JODRY PSYS KratOS main.png
Titre du projet KratOS
Cadre Projet système

Équipe Julien Reboul, Etienne Jodry
Encadrants Yves Denneulin , Gregory Mounie, Patrick Reignier


Sommaire

Présentation

Voici la page de présentation du Projet Système réalisé dans le cadre de notre 2ème année en apprentissage à l'ENSIMAG.

L'objectif de ce projet est la réalisation, à partir de presque rien, d'un noyau de système d'exploitation sur une architecture Intel x86.


Invite de commandes : b0i-Sh

Voici les commandes disponnibles

REBOUL JODRY PSYS KratOS help.png

Exit ne fait rien car nous n'avons pas trouvé comment terminer le kernel (le bloquer en hlt() ne nous semblait pas une bonne solution)

Organisation

Outils utilisés

  • Git
  • VSCode
  • Discord
  • qemu
  • Ω GDB Ω

! DISCLAIMER ! Le Live Share est bien sympa à utiliser mais il a ses limites:

  • Un Ctrl-Z annule la dernière édition du fichier sur lequel vous êtes, que ce soit la votre ou celle de votre partenaire ==> Attention à ne pas tout casser :')
  • Le partage de terminal est assez limité/buggué surtout lorsque l'hôte utilise gdb ou d'autres gadgets (gdb dashboard et le layout asm ne sont pas très bien retransmis)
  • L'édition simultanée du terminal est à utiliser avec précaution

Gestion du développement

Le développement du projet s'est fait en utilisant la capacité "Live Share" de VSCode: Ceci nous a permis de coder tous les deux en simultané sur les fichiers d'une même machine. En effet, seule la machine d'Etienne possédait le bon environnement pour la compilation et l'exécution du shell. Nous travaillions alors sur les mêmes fonctionnalités, ou presque, sans trop nous séparer le travail. Ceci nous permettait de bien challenger ce que l'autre codait en direct et ainsi de capturer un maximum de points difficiles ou complexes du premier coup. Par exemple pendant que l'un codait une structure, l'autre s'assurait que la structure correspondait bien aux différentes specs...

Ainsi côté git, nous avons directement codé sur la branche master en poussant régulièrement les fonctionnalités qui marchaient. Ceci implique que tous les commit/push sur git sont au même nom.

Côté collaboration nous avons la plupart du temps discuté via le canal de notre équipe sur Discord et fait des partages d'écran (pour se montrer l'exécution du shell en direct par exemple)

Planification

Nous n'avons pas plannifié en amont car il nous semblait difficile d'estimer le temps que nous prendrait chaque tâche. De plus les phases devaient être réalisée dans l'ordre, le chemin critique est donc l'intégralité du projet.

Nous nous comparions aux dates de completions annoncées par nos camarades des années précédentes pour mesurer notre avance/retard.

Phases de développement

Nous allons renseigner quelques sources et wikis des années précédentes qui nous ont bien aidé pour certaines phases.

Si vous vous sentez bloqués quelque part il est probable que les équipes des années précédentes aient rencontré le même problème, certains nous ont donné des indices précieux.

Un premier et un second assez généraux qui donnent des petits indices sympathiques pour toutes les phases.

Phase 1 : prise en main de l'environnement

100 %

Nous avons repris cette partie du Mini-projet système réalisé en logiciel de base, si cela a bien fonctionné pour vous vous aurez juste a fusionner vos sources. N'hésitez pas a refaire ce Projet en introduction si vous vous sentez un peu perdu.

Les documents de ce mini-projet ont l'avantage de réunir au même endroit des informations qui sont atomisées dans le wiki.

Toutes les parties du mini-projet (a part l'horloge calendaire) re-servent quelque part, ce n'est pas du temps perdu.

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

100 %

Les phases 2 et 3 sont assez mélangées, il peut être intéressant de garder en tête ce qu'il faudra faire en phase 3 pendant la réalisation de la phase 2

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

100 %

Si les méthodes de la phase 2 sont bien implémentées et que vous avez bien pensé a la filliation lors de cette dernière, il ne vous reste plus grand chose a faire pour terminer cette-ci.

Quand un processus termine il faut appeller une fonction en assembleur qui push le registre %eax dans la pile avant d'appeler votre véritable fonction de terminaison car la valeur de retour s'y trouve.

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

100 %

Ce wiki donne de bonnes idées pour la phase 4 qui peut être un peu déconcertante après avoir passé longtemps sur les processus.

C'est une phase ou il est important de coller très précisément aux spécifications qui peuvent être un peu contre intuitives, n'hésitez pas ajouter quelques champs supplémentaires dans votre structure de processus vous en aurez sans doute besoin (il faut notamment enregister une raison pour laquelle un processus a été réveillé pour gérer les cas ou on est bloqués dans une file qui a été supprimée).

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

100 %

Le Ω Saint-Graal Ω pour s'en sortir sur l'étape 5: un wiki assez clair que l'on remercie énormément. Bien utile car cette dernière est très longue et difficile, surtout au début.

Pensez bien a rendre vos interruptions appelables en mode user comme décrit ici (ce n'est pas le cas dans le mini-projet) et a donner assez de place dans la pile user pour empiler vos arguments, les dépassements de pile ne causent pas d'erreurs sur le moment mais parfois bien plus tard (dans le cas ou on écrit par dessus des instructions), ce qui les rend difficiles a débugger.

Fonction de retour

La fonction de retour qu'il faut passer aux processus change légèrement, car l'appel a exit se fait désormais par intérruption.

Le mode user n'a pas accès aux fonctions kernel et inversement, nous avons donc du instancier un morceau de pile user lors de la création de processus côté kernel et écrire dedans les instructions assembleur nécéssaires pour provoquer l'interruption de retour.

Cela peut se faire en copiant une fonction assembleur présente côté kernel.

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

100 %

Nous avons réutilisé le code fait dans le mini-projet de logiciel de base, la documentations pour l'étendre est assez directe notamment la partie Spéficications du clavier

Nous avons géré les leds clavier même s'il ne nous est pas possible de tester cette fonctionnalité.

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

100 %

Nous avons utilisé une table statique qui map des noms de commandes a des fonctions inspiré par ce qui se trouve dans les tests.

La plupart des extensions que nous avons réalisé furent des ajouts a ce Shell, notamment quelques fonctions en plus et la gestion de caractères claviers spéciaux tels que Ctrl+C,L et <-,-> qui fonctionnent comme dans un shell classique.

Une commande qui n'est pas reconnue entraine l'affichage de l'écran d'aide présent plus haut, et entrer une commande juste mais avec un argument éronné entraine l'affichage de l'aide pour cette commande spécifique.

Nous avions également prévu d'ajouter un historique des commandes mais nous avons un peu manqué de temps.

Tests Kernel

100 %

Tests User

100 %

Changelog

This is a transformation of our CHANGELOG.md file thanks to pandoc library

Notable changes and releases will be documented in this file

[1.0] - 2020-06-26

Added

  • left/right arrow functionnalities to terminal
    • can go back and correct command
      • takes effect both in echo and buffer
  • Uncompleted: top/down arrows

Changed

  • Buffer is now a list of structures of lines to handle arrows

[0.7.2] - 2020-06-25

Added

  • Fixed test 18: test if passed pointer are pointing to an authorized part of memory
  • Changed test 19: to have cons_write fitting to specification
  • queue_add_no_prio in queue.h to discard our useless prio field in our message structure
  • Added macro to test pointer
  • Added function for SIGINT while running a command
  • Shell functions:
    • banner
    • C/L: required debug in buffers
    • clear
    • Optionnal arguments
  • kbd_leds
  • sig_int/sig_clear

Changed

  • Shell
    • Ascii Logo
    • ps
      • No arg = classic ps
      • ps tree = ps with links parents/child
  • Added comments in .h, clean commented code and outdated comments
  • head use tracking only for message queues, because user memory is elsewhere
  • Limit set for user stack to 1Mo
  • Bugfix: separate counter for echo characters
  • Shell: Accepts

[0.7.1] - 2020-06-24

Added

  • STEP 7: OK
    • Shell user commands:
      • Color change
      • kill
      • exit
      • ps
      • test run (individual or all)
      • help
      • clear
    • Addition: Ascii logo
  • Found names for our project and shell

[0.6.1] - 2020-06-23

Added

  • STEP 6: OK
    • Test 19: Ok but Waiting for validation
    • Implem: keyboard_data, cons_read, cons_echo
      • Reuse of parts from v[0.2.0]
        • State BLOCKED_IO
        • Active_process
        • IT_33
    • Queues for read/write in process.c

[0.5.5] - 2020-06-22

Added

  • STEP 5: OK
    • Tests {1-20}\{18}: OK in user mode
      • DEBUG: Required lots of space in user stack
  • Stack segment selector of superviser ### Changed
  • Dynamic .globl in macros for ASM syscalls
  • Corrected TSS address pointer (0x20004)
  • Weakened condition for waking up processes

[0.5.2] - 2020-06-21

Added

  • Long enough stack size for user_start process to store registers for a syscall
    • DEBUG: Not enough size would cause ASM push to override our exit function

Changed

  • Syscalls
    • passing arguments: OK
      • Change of stack pointer (ebp -> esp)
      • IA-32 adaptation

[0.5.1] - 2020-06-19

Added

  • Syscalls
    • Registers are saved on the user side before calling IT49
    • Call of function: OK
    • Return value: OK
    • Passing arguments: NOK
  • User to Kernel: WIP
    • when user_start process ends (exit), passing to idle is buggy

Changed

  • IRQ
    • IRQs are now executable by user side processes (DPL flag)
  • Syscalls
    • User side syscalls are now generated by ASM Macros
    • IT49 handler now returns values

[0.5.0] - 2020-06-18

Added

  • Stack user
  • Mode switch
    • Mode kernel -> mode User OK
    • Mode User -> mode Kernel NOK
  • Syscalls
    • Handler IT 49
    • Transfer function call from user mode to kernel mode
    • Map syscalls to function and arguments
  • Function start & exit for user

[0.4.3] - 2020-06-17

Added

  • Test 1 -> {1-20}\{18}: OK (sauf piratage)
    • Tests {4, 6, 8, 9, 14} were actually meant for kernel
  • Debug step 4
  • Heap Use
    • Added a heap_usage global variable that keeps track of allocated memory
      • Check if newly allocated structure (msgQ, Process) does not exceed threeshold

[0.4.1] - 2020-06-16

Added

  • START: User Mode
  • FINISHED: Step 4
  • Tests-> {1-20}\{4, 6, 8, 9, 14, 18}: OK
    • Tests that do not pass are not meant for kernel mode
  • Process:
    • Convenience macros SET_ACTIVABLE and SET_EMPTY for a compact state/list change
    • head_state field: pointer to current queue head, for reinsertion when chprio
      • Important for a chprio of a process blocked in a message queue
  • message:
    • DEBUG: preceive, preset, psend
    • Convenience macro msgQ_ADD_MSG for both adding message in queue and increment of n_msg

Changed

  • Handle scrolling of console using defilement() function
  • Schedule
    • Changed ‘>’ to ‘>=’ condition in priority test to switch processes
  • Process
    • Helper function to factor change of state
      • Handles pointer to the head of state list
    • List heads:
      • Modified “empty” to “ready” and added “done”
        • Done is when the process is finished (killed or exit)
        • Done processes’ kernel stacks are freed at the begining start of any new process

[0.4.0] - 2020-06-15

Added

  • FINISHED: Primitives of MassageQueue (pcreate, preceive, psend, pdelete, preset)
  • Test 10 & 11 OK

Changed

  • Process
    • struct
      • Add message field, wake_cause
    • waitpid
      • check if children exists when calling with negative pid

[0.3.2] - 2020-06-12

Added

  • Use GDB Dashboard
  • FINISHED: Step 2
  • START: Step 4
  • Shared time system:
    • wait_clock
    • tic_PIT wake UP ASLEEP processes
  • User printf
    • cons_write
  • Message. c and .h
    • START:
      • primitives pcreate, pcount
      • Work on data structures
  • Test 7 ok
  • HOLD: Test 6, 8, 9 -> Besoin du mode user pour les interruptions

Changed

  • Scheduler verifies that an ACTIVABLE process exists
    • Neccessary because called when idle is the only awaken process
  • DEBUG:
    • Test 5:
      • Can’t kill a zombie
      • Can’t chprio a zombie
      • Can’t kill process 0
      • Can’t chprio to 0
    • Test 4 (WIP):
      • 4th assert fails (ssize ?)

[0.3.1] - 2020-06-11

Added

  • Test-driven development in start.c for Step 3
    • Test 1 -> 3 OK
    • Test 4 FAILED

Changed

  • DEBUG:
    • primitives (waitpid, chprio)
    • Parent/Children linkage

[0.3.0] - 2020-06-10

Added

  • FINISHED: Step 3
  • FINISHED: Primitives for process management
    • start; exit; kill; chprio; waitpid;
    • Process table initialization
    • Specific process: IDLE
    • Parent/Children linkage
    • context switch
    • Scheduler and process states
  • .gdbinit for automated testing
  • HOLD: KB Interupt –> TODO later (Step 6)

Changed

  • use (mem_alloc, mem_free) instead of (malloc, free)

[0.2.0] - 2020-06-09

Added

  • START Step 2 & Step 3
  • LGPLv3 licence
  • WIP: Finding a name for the project
  • WIP: Primitives for process management
    • Process struct
    • Table of process
    • start; exit; kill;
    • context switch
  • WIP: KB Interupt
    • Handling IT33

[0.1.0] - 2020-06-08

Added

  • Corrected primitives for screen management used by printf (coded last year)
  • First test run for printf and reboot (ok)
  • Interruption controller
  • Handlers for IT32 and IT40 from last year
  • START & END Step 1

Changed

  • no-pie compilation options in Makefile

Sources utiles

Doc externe

Doc officielle

Les autres doc officielles ne sont pas vraiment pertinentes et peuvent perdre plus qu'autre chose