Add TD2 Report
.
This commit is contained in:
parent
f277111e1c
commit
dbc10545f3
1 changed files with 152 additions and 0 deletions
|
@ -0,0 +1,152 @@
|
|||
---
|
||||
title: systèmes d'exploitation, TD2
|
||||
documentclass: scrartcl
|
||||
author:
|
||||
- Juliette Lenoir
|
||||
- Yorick Barbanneau
|
||||
fontsize: 13pt
|
||||
mainfont: DejaVu Serif
|
||||
geometry: [top=1.5cm, bottom=3cm, left=3cm, right=3cm]
|
||||
header-includes:
|
||||
- \definecolor{liens}{HTML}{de6a66}
|
||||
urlcolor: liens
|
||||
linkstyle: bold
|
||||
...
|
||||
|
||||
## Bilan
|
||||
|
||||
Après le premier niveau de TD effectué, alors que nous pensions pouvoir vaincre
|
||||
le boss NachOS facilement (tel ceux des jeux *Ubisoft*), nous nous sommes en
|
||||
fait retrouvé dans un *Dark Souls* like. Vous savez ce genre de jeux qui nous
|
||||
donnent on a envie de casser manettes, clavier, écran, traiter le chat comme
|
||||
dans les pubs des *Nuls* mais sur lequel on revient forcément.
|
||||
|
||||
L'objectif de ce TD a été de permettre l'exécution de programme dans Nachos
|
||||
avec plusieurs threads.
|
||||
|
||||
Il s'est déroulé en 2 parties:
|
||||
|
||||
* La première a été consacrée au multi-threading dans les programmes
|
||||
utilisateurs. Nous avons permis aux programmes utilisateurs de manipuler d
|
||||
es threads NachOS.
|
||||
* La seconde a eu pour but d'implémenter la plusieurs threads par processus.
|
||||
|
||||
Pour réaliser ces deux parties, nous avons utilisé deux appels système :
|
||||
|
||||
* un pour créer des threads (`ThreadCreate`)
|
||||
* un autre pour les détruire (`ThreadExit`)
|
||||
|
||||
Les fonctions de base de la gestions de nos threads sont présente dans le
|
||||
fichier `userthread.cc`, dans leurs définitions se font dans `usertread.h`,
|
||||
comme demandé dans le sujet du TD.
|
||||
|
||||
### Passage des paramètres depuis l'appel système
|
||||
|
||||
L'appel système `ThreadCreate` prends deux paramètres: l'adresse de la fonction
|
||||
à exécuter et l'adresse des paramètres de cette fonction. Cependant nous ne
|
||||
pouvons passer qu'une seule valeur lors de du démarrage de notre Thread:
|
||||
|
||||
```c
|
||||
Thread->Start(void * funtion, void * arguments)
|
||||
```
|
||||
|
||||
Nous avons choisi d'encapsuler l'adresse mémoire de la fonction et l'adresse
|
||||
mémoire de ses arguments dans une structre `ThreadArgs_t`:
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
int f;
|
||||
int arg;
|
||||
int stackAddr;
|
||||
} ThreadArgs_t;
|
||||
```
|
||||
|
||||
Celle-ci est effectuée dans le fichier d'entête `userthread.h`, nous parlerons
|
||||
de `int stackAddr` un peu plus loin dans ce chapitre.
|
||||
|
||||
La fonction `StartUserThread`, servant à initialiser les différents registres,
|
||||
reçoit cette structure sous la forme d'un `(void*)`. Nos ne pouvons l'utiliser
|
||||
tel quel, il nous faut donc la caster dans une variable de type `ThreadArgs_t`.
|
||||
|
||||
Afin de ne pas perdre cette structure lors de la fin de notre fonction
|
||||
`Do_ThreadCreate`, nous la positionnons sur le tas avec un `malloc`
|
||||
(`userspace.cc` ligne 50). Afin de ne pas froisser *LealSanitizer* nous n'avons
|
||||
pas oublié de libérer cette zone mémoire une fois devenueNouveau dossier inutile dans la
|
||||
fonction `StartUserThread` (ligne 38-39).
|
||||
|
||||
### Le comptage des thread.
|
||||
|
||||
Comme nous l'avons compris, la classe `AddrSpace` représente un processus -- un
|
||||
espace d'adressage. Côté noyau, tout n'est que Thread, dont certains partagent
|
||||
un même espace d'adressage. Il nous a donc **semblé légitime d'implémenter le
|
||||
comptage des Threads dans `AddrSpace`** via la variable publique `int thread`
|
||||
(définie dans `addrspace.h` ligne 50). Celle-ci est initialisée à 1 lors de
|
||||
l'instanciation: le `main` de notre programme compte lui aussi pour un thread.
|
||||
|
||||
Une fois que nous savons combien de threads sont encore "en vie", il nous est
|
||||
possible de terminer notre programme quand tous ses threads sont finis dans la
|
||||
fonction `Do_ThreadExit` (fichier `usersthread.cc` ligne 88).
|
||||
|
||||
### Gestion de la pile
|
||||
|
||||
Comme l'a démontré notre programme de test (`/test/threadtest.c`), la première
|
||||
version de notre gestion de threads était plus qu'imparfaite: elle les
|
||||
conjuguait tous avec la même pile. Nous avons alors utilisé la classe `Bitmap`
|
||||
afin de gérer les espaces de pile de nos différents threads. Sachant que nous
|
||||
réservons 256 octets de pile par thread et que notre pile gérée par `AddrSpace`
|
||||
a une taille de `UserStackSize`, nous pouvons en déduire le nombre de *"slots"*
|
||||
disponibles. Il ne faut pas oublier que notre `main` a déjà une pile et done la
|
||||
réserver a l'instanciation de notre `AddrSpace` (fichier `addrspace.cc` ligne
|
||||
145).
|
||||
|
||||
L'affectation d'un espace de pile se fait par la fonction `AllocateUserStack`
|
||||
(fichier `addrspace.h` ligne 320). Elle est appelée par `Do_ThreadCreate`
|
||||
**avant la création d'un nouveau thread** car si l'allocation echoue il faut
|
||||
tout arrêter et retourner une erreur: la célèbre *Stack Overflow*. L'adresse
|
||||
de pile de notre nouveau thread est encapsulée dans notre structure
|
||||
`ThreadArgs_t` afin de la passer à `StartUserThread`.
|
||||
|
||||
Nous avions au départ imaginé un autre mécanisme: faire attendre les threads
|
||||
jusqu'à la libération d'une place. Petit problème cependant: que se
|
||||
passera-t-il lorsqu'un programme fera une barrière?
|
||||
|
||||
### Les points bonus
|
||||
|
||||
Nous n'avons pas eu le temps d'aborder les points complémentaires.
|
||||
|
||||
## Points délicats
|
||||
|
||||
Plusieurs points ont été délicats lors de la réalisation de ce TD2.
|
||||
|
||||
Tout comme le premier TD, Il nous a fallu tout d'abord comprendre comment les
|
||||
éléments s'articulent entre eux. Cette étape nous a pris beaucoup de temps,
|
||||
nous avons obtenu **un premier thread réellement fonctionnel il y a tout juste
|
||||
deux semaines** -- après avoir tout repris de zéro. Nous avons passé une grosse
|
||||
partie de notre temps à lire, comprendre et expérimenter le code avant de
|
||||
pouvoir le modifier et le compléter.
|
||||
|
||||
La création de notre premier thread a été pour nous le plus compliqué. En
|
||||
effet, lors de cette implémentation, nous avons rencontré plusieurs erreurs de
|
||||
segmentation car notre thread n'était pas à la bonne place dans la mémoire. Une
|
||||
fois cette étape passée les choses ont été un peu plus simple.
|
||||
|
||||
## Limitations
|
||||
|
||||
Nous avons passé beaucoup de temps à comprendre comment tout les éléments
|
||||
s'articule ente eux; nous avons perdu du temps au début de la partie 1. Par
|
||||
manque de temps, nous n'avons pas pu réaliser la partie 3 Bonus.
|
||||
|
||||
La terminaison de notre processus une fois tous les threads finis ne nous
|
||||
convient pas (`Do_ThreadExit`), nous la trouvons bancale, une version plus
|
||||
élégante devrait être possible (sûrement plus simple une fois le TD3 plus
|
||||
avancé).
|
||||
|
||||
## Tests
|
||||
|
||||
Tous nos test se sont fait avec `test/threadtest.c`, nous avon adapté son code
|
||||
en fonction de ce que nous voulions tester:
|
||||
|
||||
* tester le fonctionnement d'un seul thread (Action I.7)
|
||||
* tester le fonctionnement de plusieurs threads (Action II.1)
|
||||
* tester la pile (Action II.3)
|
||||
* l'utilisation de la classe `Bitmap` (Action II.4)
|
Loading…
Add table
Add a link
Reference in a new issue