Académique Documents
Professionnel Documents
Culture Documents
Action II.2
Pour prendre en compte la terminaison de lentre, il suffit de comparer le caractre courant : if (ch == 'q' || ch == EOF ) return;
Action II.3
Pour afficher <c> au lieu de c, il suffit de lire le caractre entre dans la console : readAvail->P (); // attendre quun caractre soit entr ch = console->GetChar (); Il suffit ensuite dcrire le caractre en lencadrant par les chevrons. if (ch != '\n') //Si le caractre est un retour chariot { console->PutChar('<'); // afficher le caractre! writeDone->P (); // attendre que lcriture soit termin console->PutChar (ch);// afficher le caractre! writeDone->P (); // attendre que lcriture soit termin console->PutChar('>'); writeDone->P ();// attendre que lcriture soit termin } else { //faire le retour charriot sans afficher les chevrons console->PutChar (ch); writeDone->P (); }
Action II.4
Nous remarquons que chaque caractre prsent dans le fichier dentre (point par in) est crit dans le fichier de sortie (point par out) et est encadr par des chevrons.
Action III.4
Le fonctionnement est parfaitement le mme quavec ConsoleTest, il suffit de sparer les cas o il y a des fichiers en entre/sortie et une lecture/criture dentre clavier. else if (!strcmp (*argv, "-sc")) { if (argc == 1) SynchConsoleTest (NULL, NULL); else { ASSERT (argc > 2); SynchConsoleTest (*(argv + 1), *(argv + 2)); argCount = 3; } interrupt->Halt (); }
Action III.6
Le fonctionnement est en apparence le mme que ConsoleTest, il faut encadrer le caractre par les chevrons. while ((ch = synchconsole->SynchGetChar())!=EOF) { if (ch != '\n') { synchconsole->SynchPutChar('<'); synchconsole->SynchPutChar(ch); synchconsole->SynchPutChar('>'); } else { synchconsole->SynchPutChar(ch); } if (ch == 'q') return; }
Aprs avoir ajout la variable globale dfinissant une console synchrone, il faut mettre jour le fichier systeme.h en incluant le header synchconsole.h pour pouvoir utiliser les fonctions concernant SynchConsole (et pour pouvoir en crer une instance). Nous pouvons alors instancier linstance globale de SynchConsole dans la mthode Initialize() et grer sa destruction dans Cleanup(). Lorsque nous lanons putchar, nous voyons que le programme marche et produit laffichage attendu lors de la partie I.
Action V.2
Lappel systme SynchPutString suit le mme principe que PutChar, seul le code de la fonction dans SynchConsole et le code dexcution de lexception leve changent.
void ExceptionHandler (ExceptionType which) { . int adresse ; int adr_string ; char* tmp ; case SC_SynchPutString : adresse = machine->ReadRegister(4) ; // Rcuprer lendroit o est la //chaine tmp = new char[MAX_STRING_SIZE+1]; //creation du buffer copyStringFromMachine(adresse,tmp,MAX_STRING_SIZE); //Obtenir la chaine de la memoire MIPS synchconsole->SynchPutString(tmp);//ecrire la chaine sur la console delete[] tmp;//supprimer le buffer break; }
Dans lcriture de la fonction SynchPutString(const char s[]), nous utilisons aussi le smaphore put_taken. void SynchConsole ::SynchPutString(const char s[]) { put_taken->P(); //Prendre le semaphore int i =0; char c = s[i]; //recuprer le premier caractere while (c != \0 && c!=EOF){ console->PutChar(c); //on ecrit le premier caractere writeDone->P(); //on attend la fin de lecriture i++; c=s[i]; } console->PutChar(\0); writeDone->P(); put_taken->V(); //on libere le semaphore }
Action V.3
En testant notre programme avec une chaine plus grande que la taille maximal dun string (ici dfini 20 caractres), nous remarquons que seulement les 20 premiers sont affichs.
Partie VI. Mais comment sarrter ? Si nous enlevons lappel halt() la fin du main de putchar.c. Il ny a plus de valeur retourne donc il y a un warning la compilation. Ce warning est trait comme une erreur. Pour ne plus faire appel Halt, il faut retourner une valeur quelconque la place. En testant le programme putchar.c avec une valeur de retour, nous remarquons que lexcution est normale jusqu laffichage du type dexception : Unexpected user mode exception 1 1 . Nous remarquons que lexception a le type 1, ce code dappel systme est SC_Exit. Il faut donc grer un cas pour cette exception dans le gestionnaire dexception ExceptionHandler. De plus, quand nous regardons le code assembleur qui gre lappel dun programme, nous remarquons quelle se fait en plusieurs tapes : La gestion dun programme se faire ltiquette __start : jal main move $4,$0 jal Exit Nous voyons qu la fin du main, sil ny a pas lappel Halt, le programme ira ltiquette Exit. Il y aura donc un appel systme Exit. Pour grer la valeur de retour, il faut aller voir dans le fichier test/start.S. En effet, il faut aussi regarder le code assembleur. Nous savons que la valeur de retour dune fonction est
stocke dans le registre r2. Cependant lors de lexcution de Exit, nous remarquons que le code dappel systme est stock dans le registre r2. Pour avoir le code de retour, une possibilit est denregistre la valeur du registre r2 dans un autre registre, par exemple le registre r4 (il ny a pas paramtre lors de la fin dun programme). Il suffit dajouter linstruction : move $4, $2 avant linstruction denregistrement du code SC_Exit dans r2.
void ExceptionHandler (ExceptionType which) { . int retour; case SC_Exit : retour = machine->ReadRegister(4) ; //recuperer la valeur de retour printf(la valeur retournee du programme est %u\n,retour); interrupt->Halt() ;//arrter la machine break; }
Action VII.2
Lappel systme SynchGetString suit le mme principe que PutChar, seul le code de la fonction dans SynchConsole et le code dexcution de lexception leve changent. Pour lcriture de SynchGetString, je me suis inspir de ce texte cette description :
char *fgets (char *s, int size, FILE *stream); fgets() lit au plus size - 1 caractres depuis stream et les place dans le buffer point par s. La lecture s'arrte aprs EOF ou un retour-chariot. Si un retour-chariot (newline) est lu, il est plac dans le buffer. Un caractre nul '\0' est plac la fin de la ligne.
void SynchConsole ::SynchGetString(char *s,int n) { get_taken->P(); //prendre le smaphore de lecture readAvail-> P();//attente de lecture char c = console->GetChar(); // on lit le premier caractre int i = 0; s[i] = c; i++;
while (i<(n-1) && c!=EOF && c!=\n && c!=\0 && c!=|r){ readAvail->P(); c = console->GetChar(); if (c != EOF && c != \0){ s[i] = c; i++ } }
s[i] = \0; get_taken-> V(); } Dans le gestionnaire dexception, le cas de SynchGetString doit tre le symtrique de SynchPutString, nous devons rcuperer le string, puis le copier dans la machine MIPS. void ExceptionHandler (ExceptionType which) { int adr_string; int taille; char* string; case SC_SynchGetString : adr_string=machine->ReadRegister(4) ; taille = machine->ReadRegister(5); tmp = new char[MAX_STRING_SIZE]; writeStringtoMachine(adr_string,string,taille); synchconsole->SynchGetString(tmp); delete[] tmp; break; } void writeStringtoMachine(int debut, char* tableau, int size) { int d = debut; int i =0; while(i<size && tableau[i] != \0 && tableau[i] != EOF) { machine->WriteMem(d,1,(int)tableau[i]); i++;d++; } machine-> WriteMem(d,1,(int)\0); } Sil y a plusieurs appels de cette fonction par plusieurs threads, il peut y avoir des comportements nfastes, en effet, les threads peuvent lire les caractres de la chaine en mme temps et donc vont juste avoir un morceau de la chaine.
Action VII.3
Le protocole de snprintf est : snprintf (char *str, size_t size, const char *format, ...);
Le premier argument de cette fonction est la chaine de caractres qui contiendra le rsultat de la conversion. Le deuxime argument est justement le nombre maximal de caractres qui seront renvoys dans cette variable. Le paramtre suivant est le format suivi des variables qui devront tre converties selon ce format.
void SynchConsole ::SynchPutInt(int n) { char c[10] ; snprintf(c,10, %d ,n) ; synchconsole->SynchPutString(chaine) ; } void ExceptionHandler (ExceptionType which) { int valeur; case SC_SynchPutInt : valeur =machine->ReadRegister(4) ; synchconsole->SynchPutInt (valeur); break; }
Le protocole de sscanf est sscanf ( string $str , string $format,) sscanf() lit des donnes dans la chane str, l'interprte en fonction du format format, puis enregistre ladresse des pointeurs passs en paramtre les donnes concordantes au(x) format(s). void SynchConsole ::SynchGetInt(int *n) { char c[10] ; synchconsole->SynchGetString(c,10) ; sscanf(c, %d ,n) ; } void ExceptionHandler (ExceptionType which) { int valeur; case SC_SynchGetInt : adresse =machine->ReadRegister(4) ; synchconsole->SynchGetInt (&entier); machine->WriteMem(adresse,sizeof(int),entier) ; break; }