Projet de Systèmes (Master 1 II 2010-2011)

Hypnotix

Informations

Le projet est à réaliser par groupe de trois personnes au plus.

But

Construire en langage C une machine virtuelle contenant des composants orientés systèmes comme : un gestionnaire de processus avec ordonnanceur préemptif, un mécanisme d'interruption logicielle par signaux asynchrones, un moniteur de synchronisation.

Hypnotix

La machine Hypnotix possède deux aspects : des instructions ordinaires (affectation, calculs arithmétiques élémentaires, test et sauts) et des instructions orientées système (fork, etc). La machine est donc à la fois un processeur au sens habituel mais aussi un système d'exploitation (cette caractéristique particulière n'existe pas dans la nature, elle n'est présente qu'à des fins de simplification). La machine/système exécute donc des codes binaires Hypnotix. Ces derniers sont obtenus par assemblage (compilation élémentaire d'un code source Hypnotix en code objet Hypnotix par l'intermédiaire de l'assembleur assembler donné). La machine/système Hypnotix devra permettre l'exécution de binaires; une telle exécution s'appelle un processus.

Démarrage d'Hypnotix

À son démarrage, le système Hypnotix initialise toutes les structures nécessaires à son bon fonctionnement puis se met en attente de commandes.

En régime de croisière

Dans ce régime, la machine Hypnotix exécute les divers processus (s'il en existe) et réagit aux commandes utilisateurs. Ces deux comportements doivent cohabiter sans être interbloquants. L'exécution des processus doit s'effectuer en mode temps partagé : chaque processus reçoit un quantum de temps (pour simplifier ce quantum correspond à un nombre d'instructions à exécuter) à la suite duquel l'ordonnanceur choisira un nouveau processus à exécuter (le nouveau pouvent être le même que l'ancien!). Les commandes utilisateurs sont transmises au système via une file de messages (un message incarnant une commande). Le système est prévenu qu'une commande est à traiter en réceptionnant un signal Unix. Le système se doit de réagir au plus vite aux commandes utilisateurs.

Hypnotix / Unix

Le système Hypnotix sera donc composé de deux processus Unix :

Les processus Hypnotix

Un processus Hypnotix sera une structure entièrement contenue dans la mémoire Hypnotix (voir plus loin). Cette structure devra contient toutes les informations nécessaires à la bonne exécution du programme associé : structure de contrôle, pointeur vers les instructions, données et pile.

L'ensemble constitué des instructions, données et pile d'un processus constituent son espace d'adressage :

On notera que la machine/système Hypnotix ne manipule qu'un seul type de données.

La structure de contrôle du processus contient différentes informations que l'on jugera nécessaires d'y mettre et qui doivent permettre une bonne exécution du processus associé, on y trouvera par exemple: l'adresse physique de la zone d'instruction, l'adresse physique de la zone de données, l'adresse physique de la pile, le numéro de l'instruction en cours d'exécution, l'état du processus, son code de retour, masque des signaux, etc.

On notera qu'un binaire Hypnotix fait toujours des adressages virtuels. Ainsi, dans un processus, une instruction faisant référence au chargement d'une donnée située à l'adresse 10, ne fait pas référence à l'adresse machine Hypnotix 10 mais à la 10ième donnée de la zone de données du processus (idem pour les instructions de contrôle de l'exécution qui font référence à des adresses en zone d'instruction et pour la pile dans la zone de pile...).

La Mémoire Hypnotix

La mémoire du système Hypnotix sera nécessairement constituée d'une unique zone d'octets de la machine hôte (voir l'exécuteur de code processor donné en exemple).

Dans cette mémoire on trouvera donc les instructions les données et piles des processus qui s'exécutent à un moment donné.

(Projet en mode avancé) On pourra envisager :

Le langage Hypnotix

Ce langage assez rudimentaire permet d'écrire plus simplement des programmes à exécuter par la machine Hypnotix. Le programme source peut être assemblé (en utilisant la commande assembler fournie et qui prend deux paramètres : le premier est le nom du fichier contenant le code source et le second le nom du fichier qui contiendra le code objet) pour obtenir un binaire Hypnotix. Pour faciliter la tâche il est conseillé de nommer les binaires en utilisant une seule lettre (éventuellement agrémentée d'une « extension »), comme par exemple f.ist ou simplement f (pour comprendre pourquoi, consultez le description de l'instruction EXEC plus loin).

La conception d'un assembleur dépassant le cadre de ce cours, cet outil vous est fourni (avec ses sources). Nous déconseillons vivement aux étudiants de s'attacher à en comprendre le fonctionnement dans l'immédiat. Faites ce qui est demandé, si le cœur vous en dit, vous pourrez toujours l'examiner par la suite. Par contre il est vivement conseillé de consulter le code du desassembler qui lui vous donnera d'excellentes indications sur la structure du code machine et sur la façon d'interpréter ce code. Une autre excellente idée est aussi d'observer le code du processeur (de nom processor) qui permet d'exécuter un binaire Hypnotix (seulement les instructions ordinaires évidemment!).

Le langage est constitué de deux types d'instructions:

Dans le tableau suivant, on trouvera la description de toutes les instructions et leur correspondance (approximative) dans l'API POSIX en langage C.

Mnémonique Arguments instruction C/Unix
ASSIGN réf,réf_ou_cste réf = réf_ou_cste;
ASSIGN+ réf,réf_ou_cste réf += réf_ou_cste;
ASSIGN- réf,réf_ou_cste réf -= réf_ou_cste;
ASSIGN* réf,réf_ou_cste réf *= réf_ou_cste;
IF réf_ou_cste,réf_ou_cste,étiquette if (réf_ou_cste==réf_ou_cste) goto étiquette;
JUMP étiquette goto étiquette;
CALL étiquette étiquette();
RET
return;
FORK réf réf = fork();
EXEC réf_ou_cste exec(réf_ou_cste);
EXIT réf_ou_cste exit(réf_ou_cste);
WAIT réf,réf réf = wait(réf);
SIGNAL réf_ou_sig,étiquette signal(réf_ou_cste,étiquette);
KILL réf_ou_sig,réf kill(réf_ou_cste,réf);
READ réf read(STDIN_FILENO,réf,1);
WRITE réf_ou_cste write(STDOUT_FILENO,réf_ou_cste,1);
GETPPID réf réf = getppid();
LCK cste semop() avec semop = -1;
UNLCK cste semop() avec semop = +1;
SETPRIO cste nice(cste) ou setpriority(cste...)

Les arguments sont de quatre types (attention, dans ce qui suit les valeurs seront toujours exprimées relativement à l'espace d'adresse du processus) :

On notera la possibilité de commenter du code Hypnotix en commençant une ligne par le caractère /.

Un assembleur Hypnotix est fourni. Il ne permet d'écrire qu'une seule instruction par ligne de texte, et une instruction n'est jamais située en début de ligne, mais est toujours précédée d'au moins un espace ou une tabulation.

IMPORTANT : un programme Hypnotix doît obligatoirement contenir une instruction étiquetée par debut et permettant d'indiquer le point d'entrée du programme (équivalent du main() du C).

Ce qui suit est un exemple de programme source Hypnotix. Cet exemple comme ceux fournis ne sont que des exemples rien de plus, il vaut mieux les étudier de près afin de se faire une idée de la programmation de la machine/système Hypnotix. Une fois cette tâche accomplie, il est plus que fortement conseillé d'en écrire par vous-même!

/ On commence par compter jusqu'a 10
debut:
ASSIGN 13,#0
incr:
ASSIGN+ 13,#1
IF 13,#10,fin_incr
JUMP incr
/ On essaye d'appeler une fonction
fin_incr:
CALL remise_a_zero
/ On tente de capturer SIGUSER
SIGNAL U_SIGUSER,sig_handler
/ Et un petit fork/exec/wait
FORK 1
IF 1,#0,fils
/ Le pere attend
WAIT 2,3
/ Il ecrit 'b'
WRITE #65
EXIT #0
remise_a_zero:
ASSIGN 13,#0
RET
/ Le code du fils!
fils:
/ Il envoie un SIGUSER a son pere
GETPPID 5
KILL U_SIGUSER,5
/ Il exec sur 'a'
EXEC #64
EXIT #1
sig_handler:
WRITE #64
RET

Le lange de contrôle

Rappellons que le système Hypnotix peut être contrôlé par l'intermédiaire d'un processus Unix particulier désigné ici par le contrôleur. Il doit donc permettre de modifier le comportement ou obtenir diverses informations du système Hypnotix. Parmi celles-ci (on peut en rajouter à volonté), on devra trouver :

Matériel fourni

Vous trouverez dans le ficher hypnotix.tar.gz l'ensemble des sources utiles pour démarrer le projet.

Nous insistons: ll est formellement déconseillé de modifier quoi que ce soit dans les programmes fournis en particulier dans l'assembleur, vous y perdriez un temps considérable pour un gain nul ou presque.

Le seul fichier à modifier (éventuellement) est le Makefile pour paramétrer la compilation sur votre système. Les seuls programmes intéressants à étudier sont: desassembler.c et processor.c.

L'assembleur a pour syntaxe d'appel: assembler source objet.

Le désassembleur a pour syntaxe d'appel: desassembler < objet.

Le processeur a pour syntaxe d'appel: processor < objet. Note : le processeur n'est qu'une base de travail.

Le projet

Il est demandé d'écrire deux programmes en langage C : Hypnotix et son contrôleur.

Le système Hypnotix devra utiliser un adressage virtuel pour les processus. Adressage qui pourra permettre de partager le code lorsque différents processus exécuteront le même code.

Particularités

L'instruction EXEC qui permet de recouvrir le code du processus courant par un nouveau code obtient le nouveau code à charger en effectuant des lectures sur le fichier (du système Unix) dont le nom est donnée par le paramètre. Ce dernier est toujours un entier (obtenu éventuellement par référence) utilisé comme code ASCII pour obtenir le nom du fichier à charger. Ainsi une instruction comme EXEC #65 permettra de charger le programme contenu dans le fichier A (avec une extension prédéfinie si nécessaire).

L'instruction WAIT prend deux arguments, le premier sera l'adresse où sera rangée l'identité du fils terminé et la seconde celle contenant le code de retour.

Les instructions READ ou WRITE ne permettent de lire ou d'écrire qu'un seul caractère à la fois et dont le code ASCII est donné en argument (écrire) ou renvoyé par le système (lire). Si l'écriture est immédiate (par exemple affichage d'un message: le processus numéro 87 a écrit le caractère ASCII 64 'A'), la lecture provoque le blocage du processus en cours tant qu'aucune donnée ne lui a été fournie par l'interface (on peut envisager un tampon de lecture).

Pour le reste...

Consignes

Les consignes les plus utiles (dates des soutenances, etc) seront fournies dans ce document au fur et à mesure de leur nécessité.