624 | | Nous allons désormais avoir deux exécutables: le noyau et l'application. Dans cette étape, nous allons voir comment le noyau fait pour appeler l'application, alors que celle-ci n'est pas compilée en même temps que le noyau. Nous allons passer du noyau à l'application à la fin de la fonction `kinit()`. |
625 | | |
626 | | En revanche, dans cette étape, nous n'allons pas mettre en place la gestion des syscalls. C'est-a-dire qu'il ne sera pas possible de revenir dans le noyau depuis l'application. C'est bien entendu une étape intermédiaire, parce qu'il faut normalement absolument pouvoir invoquer le noyau depuis l'application pour accéder aux périphériques. |
627 | | Toutefois, pour pouvoir quand même accéder aux registres de périphériques, nous allons exceptionnellement exécuter l'application en mode kernel. Ainsi, l'application pourra accéder aux adresses de l'espace d'adressage réservées aux mode `kernel`. |
| 624 | Nous allons désormais avoir deux exécutables: le noyau et l'application. Dans cette étape, nous allons voir comment le noyau fait pour appeler l'application, alors même que celle-ci n'est pas compilée en même temps que le noyau. Nous allons passer du noyau à l'application à la fin de la fonction `kinit()`. |
| 625 | |
| 626 | Nous allons donc entrer dans l'application, en revanche, dans cette étape, nous n'allons pas mettre en place la gestion des syscalls. C'est-a-dire qu'il ne sera pas possible de revenir dans le noyau depuis l'application. C'est bien entendu une étape intermédiaire, parce qu'il faut absolument pouvoir invoquer le noyau depuis l'application pour accéder aux périphériques. |
| 627 | Pour pouvoir quand même accéder aux registres de périphériques, nous allons **exceptionnellement** exécuter l'application en mode kernel. Ainsi, l'application pourra accéder aux adresses de l'espace d'adressage réservées aux mode `kernel`. |
665 | | - Dans le fichier `user/crt0.c`, c'est la fonction `_start()` |
666 | | ''''''''''''''' |
667 | | }}} |
668 | | 1. Quelle est la fonction du noyau qui appelle cette fonction et dans quel ? |
669 | | {{{#!protected ------------------------------------------------------------------------------------ |
670 | | ''''''''''''''' |
671 | | - Dans le fichier `kernel/kinit.c` et c'est la fonction `kinit()`. |
| 665 | - Dans le fichier `user/crt0.c`, c'est la fonction `_start()`. |
| 666 | ''''''''''''''' |
| 667 | }}} |
| 668 | 1. Quelle est la fonction du noyau qui appelle cette fonction et dans quel fichier? |
| 669 | {{{#!protected ------------------------------------------------------------------------------------ |
| 670 | ''''''''''''''' |
| 671 | - C'est la fonction `kinit()`, dans le fichier `kernel/kinit.c`. |
758 | | - Vous allez ajouter un appel système nommé `SYSCALL_CPUID` qui rend le numéro du processeur. Nous allons lui attribuer le numéro 4 (notez que ces numéros de services n'ont rien à voir avec les numéros utilisés pour le simulateur MARS). Pour ajouter un appel système, vous devez modifier les fichiers : |
759 | | - `common/syscalls.h` : pour ajouter le numéro de service |
760 | | - `kernel/ksyscall.c` : pour modifier le vecteur de syscall |
761 | | - `kernel/hcpu.S` : pour ajouter la fonction `int cpuid(void)` (la même que celle demandé en **B.1**) |
762 | | - `kernel/hcpu.h` : pour déclarer le prototype de `int cpuid(void)` (comme pour **B.1**) |
763 | | |
764 | | |
765 | | |
766 | | == B4. Ajout de la librairie C |
| 761 | |
| 762 | - Vous allez ajouter un appel système nommé `SYSCALL_CPUID` qui rend le numéro du processeur. Nous allons lui attribuer le numéro 4 (notez que ces numéros de services n'ont rien à voir avec les numéros utilisés pour le simulateur MARS). Pour ajouter un appel système, vous devez modifier les fichiers : `common/syscalls.h`, `kernel/ksyscall.c`, `kernel/hcpu.S` et `kernel/hcpu.h`.cpuid(void)`. |
| 763 | |
| 764 | |
| 765 | |
| 766 | == B4. Ajout de la librairie C pour l'utilisateur |
773 | | L'application utilisateur n'est pas censée utiliser directement les appels système. Elle utilise une librairie de fonctions standards (la libc POSIX, mais pas seulement) et ce sont ces fonctions qui réalisent les appels système. Toutes les fonctions de la libc n'utilisent pas les appels système. Par exemple, les fonctions `int rand(void)` ou `int strlen(char *)` (rendent, respectivement, un nombre pseudo-aléatoire et la longueur d'une chaîne de caractères) n'ont pas besoin du noyau. Les librairies font partie du système d'exploitation mais elles ne sont pas dans le noyau. |
774 | | |
775 | | Le terme « librairie » vient de l'anglais « library » qui signifie bibliothèque. On utilise souvent le mot librairie même si le sens en français n'est pas le même que celui en anglais. Disons que, dans notre contexte, les deux mots sont synonymes. |
776 | | |
777 | | Normalement, les librairies système sont des « vraies » librairies au sens `gcc` du terme. C'est-à-dire des archives de fichiers objet (`.o`). Ici, nous allons simplifier et ne pas créer de librairie, mais seulement un fichier objet `libc.o` contenant toutes les fonctions. Ce fichier objets doit être lié avec le code de l'application. |
778 | | |
779 | | L'exécutable de l'application utilisateur est donc composé de deux parties : le code de l'application et le code de la librairie et nous allons répartir le code dans deux répertoire `uapp` pour les fichiers de l'application et `ulib` pour les fichiers qui ne sont pas l'application, c'est-à-dire la libc, mais aussi le fichier `ldscript` et le fichier `crt0.c`. |
| 773 | L'application utilisateur n'est pas censée utiliser directement les appels système. Elle utilise une librairie de fonctions standards (la `libc` POSIX, mais pas seulement) et ce sont ces fonctions qui réalisent les appels système. Toutes les fonctions de la `libc` n'utilisent pas les appels système. Par exemple, les fonctions `int rand(void)` ou `int strlen(char *)` (rendent, respectivement, un nombre pseudo-aléatoire et la longueur d'une chaîne de caractères) n'ont pas besoin du noyau. Les librairies font partie du système d'exploitation mais elles ne sont pas dans le noyau. |
| 774 | |
| 775 | ''Le terme « librairie » vient de l'anglais « library » qui signifie bibliothèque. On utilise souvent le mot librairie même si le sens en français n'est pas le même que celui en anglais. Disons que, dans notre contexte, les deux mots sont synonymes.'' |
| 776 | |
| 777 | Normalement, les librairies système sont des « vraies » librairies au sens `gcc` du terme. C'est-à-dire des archives de fichiers objet (`.o`). Ici, nous allons simplifier et ne pas créer une ''vraie'' librairie, mais seulement un fichier objet `libc.o` contenant toutes les fonctions. Ce fichier objets doit être lié avec le code de l'application. |
| 778 | |
| 779 | L'exécutable de l'application utilisateur est donc composé de deux parties : d'un côté, le code de l'application et, de l'autre, le code de la librairie `libc` (+ `crt0`). Nous allons répartir le code dans deux répertoires `uapp` pour les fichiers de l'application et `ulib` pour les fichiers qui ne sont pas l'application, c'est-à-dire la `libc`, le fichier `crt0.c` mais aussi le fichier ldscript `user.ld`. |