Page principale   Liste par ordre alphabétique   Liste des composants   Liste des fichiers   Composants   Déclarations  

systeme.c

Aller à la documentation de ce fichier.
00001 /**
00002  * @file systeme.c
00003  * Source de base definissant le fonctionnement du systeme.
00004  * Gere par exemple :
00005  * - l'initialisation des differents elements du programme
00006  * - la reception et l'interpretation des signaux provenant de l'interface
00007  * S'appuie pour cela sur les fonctions de interpreteur.c 
00008  */
00009 
00010 #include "commandes.h"
00011 #include "systeme.h"
00012 
00013 /**************************************************************************************
00014  Fait par Martin Ludovic
00015 **************************************************************************************/
00016 
00017 /**
00018  * Initialise la memoire principale
00019  * \return rien
00020  */
00021 void init_mem () {
00022   page_t page_mem;
00023   mot_t mot_mem;
00024   int i,j;
00025   int mem_d;
00026 
00027   for (i=0 ; i<4 ; i++) {
00028     mot_mem[i] = (octet_t)0;
00029   }
00030   // Initialisation de la 1ere page
00031   // Le 1er mot contient le plus petit pid libre
00032   mot_mem[3] = (octet_t)DEBUT_T_PROC;
00033   memcpy(page_mem[0], mot_mem, T_MOT);
00034   // Initialisation de la table des processus
00035   mot_mem[3] = 0;
00036   changer_etat(E_MORT,mot_mem);
00037   for (i=1 ; i<N_MAX_PROC+1 ; i++) {
00038     memcpy(page_mem[i], mot_mem, T_MOT);
00039   }
00040   // Initialisation de la table des pages libres
00041   mot_mem[0] = (octet_t)2; // le plus petit num de page mem lire
00042   mot_mem[1] = (octet_t)0; // position courante ds la table des pages swap libres
00043   mot_mem[2] = (octet_t)PAGE_VIDE;
00044   mot_mem[3] = (octet_t)PAGE_VIDE;
00045   for (i=N_MAX_PROC+1 ; i<NMPPP ; i++) {
00046     if (i == N_MAX_PROC+2) {
00047       mot_mem[0] = (octet_t)PAGE_VIDE;
00048       mot_mem[1] = (octet_t)PAGE_VIDE;
00049     }
00050     memcpy(page_mem[i], mot_mem, T_MOT);
00051   }
00052   memcpy(mem[NUM_PAGE_META], page_mem, T_PAGE);
00053   // Initialisation de la 2eme page
00054   for (i=0 ; i<NMPPP ; i++) {
00055     for (j=0 ; j<T_MOT ; j++) {
00056       mot_mem[j] = (octet_t)j+i*T_MOT;
00057     }
00058     memcpy(page_mem[i], mot_mem, T_MOT);
00059   }
00060   memcpy(mem[NUM_PAGE_SWAP], page_mem, T_PAGE);
00061   // Pour le debuggage...
00062   mem_d=open("./f.mem",O_CREAT|O_TRUNC|O_RDWR,0666);
00063   write(mem_d,mem,NPP*NMPPP*T_MOT);
00064 }
00065 
00066 /**
00067  * Initialise la memoire secondaire (swap)
00068  * \return
00069  * - -1 en cas d'echec
00070  * - 0 en cas de reussite
00071  */
00072 int init_swap () {
00073   page_t page_swap;
00074   mot_t mot_swap;
00075   int i,j;
00076   int num_page_swap,num_page_suivante;
00077 
00078   for (i=0 ; i<4 ; i++) {
00079     mot_swap[i] = (octet_t)0;
00080   }
00081   // Ouverture du fichier simulant la mem secondaire
00082   if ((swap_d=open("f.swap",O_RDWR|O_CREAT|O_TRUNC,0666)) == -1) {
00083     fprintf(stderr,"Impossible d'ouvrir ou de creer le fihier swap\n");
00084     return -1;
00085   }
00086   // Creation d'un swap 'vide'
00087   // Remplissage du swap pour qu'il fasse NPPS*NMPPP*T_MOT*8 octets
00088   for (i=0 ; i<NMPPP ; i++) { // Page vide
00089     memcpy(page_swap[i], mot_swap, T_MOT);
00090   }
00091   for (i=0 ; i<NPPS ; i++) {
00092     if (write(swap_d,page_swap,T_PAGE) != T_PAGE) {
00093       fprintf(stderr,"Impossible d'initialiser le fihier swap\n");
00094       return -1;
00095     }
00096   }
00097   if (lseek(swap_d,0,SEEK_SET) == -1) {
00098     return -1;
00099   }
00100   // Creation de la table des pages libres du swap
00101   num_page_suivante = NMPPP*T_MOT - 1; // Les NMPPP*T_MOT 1eres pages sont stockees ds la mem RAM
00102   num_page_swap = num_page_suivante + 1;
00103   while (num_page_swap != NO_MORE_SWAP) {
00104     // Constitution d'une page contenant des numeros de pages libres
00105     for (i=0 ; i<NMPPP ; i++) {
00106       for (j=0 ; j<T_MOT ; j++) {
00107         if (num_page_swap >= NPPS)
00108           num_page_swap = NO_MORE_SWAP;
00109         mot_swap[j] = (octet_t)num_page_swap;
00110         if (num_page_swap != NO_MORE_SWAP)
00111           num_page_swap++;
00112       }
00113       memcpy(page_swap[i], mot_swap, T_MOT);
00114     }
00115     // Ecriture de la page
00116     if (lseek(swap_d,num_page_suivante*T_PAGE,SEEK_SET) == -1) {
00117       return -1;
00118     }
00119     if (write(swap_d,page_swap,T_PAGE) != T_PAGE) {
00120       return -1;
00121     }
00122     num_page_suivante = num_page_swap-1;
00123   }
00124   return 0;
00125 }
00126 
00127 /**
00128  * Lancement d'un programme: creation d'un processus avec une table des pages et remplissage 
00129  * de la zone de code.
00130  * Rem:
00131  * - La zone de pile est allouee dynamiquement durant l'execution du processus
00132  * - La zone de donnees est fixee par la 1ere instruction (DONNEES)
00133  * \param fic : nom du fichier contenant le code objet du programme a lancer
00134  * \return 
00135  * - -1 en cas d'echec
00136  * - 0 sinon
00137  */
00138 int lancer_prog (char* fic, int pid) {
00139   mot_t mot,mot_tp;
00140   int num_mot_tp=0;
00141   page_t page_lue;
00142   void *page_vide;
00143   int i;
00144   int num_table_page,num_page;
00145   int desc;
00146   int lu;
00147 
00148   // Cherche un numero de processus libre
00149   if (pid == 0) {
00150     if ((pid=pid_libre()) < 1)
00151       return -1; 
00152   }
00153   // Cherche une page libre en memoire principale pour la table des pages du proc
00154   if ((num_table_page=page_forcee(pid)) < 1) {
00155     liberer_pid(pid);
00156     return -1;
00157   }
00158   // Initialise cette page
00159   for (i=0 ; i<T_MOT ; i++) {
00160     mot[i] = (octet_t)0;
00161     mot_tp[i] = (octet_t)0;
00162   }
00163   for (i=0 ; i<NMPPP ; i++) {
00164     if (ecrire_mot_mem(i,num_table_page,mot) == -1) {
00165       liberer_page(num_table_page);
00166       liberer_pid(pid);
00167       return -1;
00168     }
00169   }
00170   // Initialise l'entree correspondant au processus ds la table des processus
00171   changer_type_pp(PP_RAM,mot);
00172   changer_etat(E_ELIGIBLE,mot);
00173   mot[3] = (octet_t)num_table_page;
00174   mot[1] = (octet_t)0;
00175   mot[0] = (octet_t)S_NULL;
00176   if (ecrire_mot_mem(pid,NUM_PAGE_META,mot) == -1) {      
00177     liberer_page(num_table_page);
00178     liberer_pid(pid);
00179     return -1;
00180   }
00181   // Traitement de la zone de code
00182   // Ouverture du fichier objet
00183   if ((desc=open(fic,O_RDONLY)) == -1) {
00184     liberer_page(num_table_page);
00185     liberer_pid(pid);
00186     return -1;
00187   }
00188   // Remplissage des pages de code
00189   if ((page_vide=calloc(1,sizeof(page_t))) == NULL) {
00190     liberer_page(num_table_page);
00191     liberer_pid(pid);
00192     return -1;
00193   }
00194   memcpy(page_lue,page_vide,sizeof(page_t));
00195   if ((lu=read(desc,page_lue,sizeof(page_t))) == -1) {
00196     liberer_page(num_table_page);
00197     liberer_pid(pid);
00198     close(desc);
00199     free(page_vide);
00200     return -1;
00201   }
00202   if (lu == 0) { // On verifie que le fichier a executer n'est pas vide
00203     fprintf(stderr,"Le fichier %s est vide!\n",fic);
00204     liberer_page(num_table_page);
00205     liberer_pid(pid);
00206     close(desc);
00207     free(page_vide);
00208     return -1;
00209   }
00210   while (lu != 0) {
00211     // Recherche une page physique libre en RAM
00212     switch (num_page=page_libre(pid)) {
00213     case -1:
00214       supprimer_proc(pid); // Supprime le proc et ses pages
00215       free(page_vide);
00216       close(desc);
00217       return -1;
00218     case -2:
00219       // Plus de page libre en RAM
00220       // Recherche une page swap libre
00221       switch (num_page=page_swap_libre(pid)) {
00222       case -2:
00223         fprintf(stderr,"Impossible de continuer le lancement du processus: liberer de la mem\n");
00224       case -1:
00225         supprimer_proc(pid);
00226         free(page_vide);
00227         close(desc);
00228         return -1;
00229       default:
00230         // Copie la page lue dans une page physique du swap
00231         if (ecrire_page_swap(page_lue,num_page) == -1) {
00232           supprimer_proc(pid);
00233           free(page_vide);
00234           close(desc);
00235           return -1;
00236         }
00237         // Entre cette page ds la table des pages du processus
00238         mot_tp[2] = (octet_t)PP_SWAP;
00239         mot_tp[3] = (octet_t)num_page;
00240         if (ecrire_mot_mem(num_mot_tp,num_table_page,mot_tp) == -1) {
00241           supprimer_proc(pid);
00242           free(page_vide);
00243           close(desc);
00244           return -1;
00245         }
00246       }
00247       break;
00248     default:
00249       // Copie la page lue dans une page physique de la RAM mot par mot
00250       for (i=0 ; i<NMPPP ; i++) {
00251         if (ecrire_mot_mem(i,num_page,page_lue[i]) == -1) {
00252           supprimer_proc(pid);
00253           free(page_vide);
00254           close(desc);
00255           return -1;
00256         }
00257       }
00258       // Entre cette page ds la table des pages du processus
00259       mot_tp[2] = (octet_t)PP_RAM;
00260       mot_tp[3] = (octet_t)num_page;
00261       if (ecrire_mot_mem(num_mot_tp,num_table_page,mot_tp) == -1) {
00262         supprimer_proc(pid);
00263         free(page_vide);
00264         close(desc);
00265         return -1;
00266       }
00267     }
00268     num_mot_tp ++;
00269     memcpy(page_lue,page_vide,sizeof(page_t));
00270     if ((lu=read(desc,page_lue,sizeof(page_t))) == -1) {
00271       supprimer_proc(pid);
00272       free(page_vide);
00273       close(desc);
00274       return -1;
00275     }
00276   }
00277   free(page_vide);
00278   return 0;
00279 }
00280 
00281 
00282 /**************************************************************************************
00283  Fait par Ouachani Mourad
00284 **************************************************************************************/
00285 
00286 /**
00287  * Handler interceptant SIGUSR1 qui demande au systeme d'executer une nouvelle instruction
00288  * \param sig : le num du signal
00289  * \return rien
00290  */
00291 void top_horloge_handler (int sig) {
00292   int pid;
00293   int i;
00294 
00295   sig = 0; // juste pour eviter au compilo de raler...
00296   // Interprete tous les signaux de la table des processus
00297   for (i=1 ; i<=N_MAX_PROC ; i++) {
00298     interprete_signaux(pid);
00299   }
00300   // Recherche le prochain processus a executer
00301   pid = liste_next_pid(liste_proc);
00302   // interprete l'instruction courante du processus pid
00303   next_inst(pid);
00304 }
00305 
00306 /**
00307  * Handler interceptant SIGUSR2 qui averti le systeme qu'une requete a ete envoyee ds le tube
00308  * \param sig : le num du signal
00309  * \return rien
00310  */
00311 void interface_handler (int sig) {
00312   sig=0;
00313   lire_tube();
00314 }
00315 
00316 /**
00317  * Lire le contenue du tube
00318  * \return 
00319  * - -1 en cas d'echec
00320  * - 0 sinon
00321  */
00322 int lire_tube(){
00323   struct message mes_lus;
00324   int lu;
00325 
00326   if( (fifo = open( FIFO_NAME, O_RDONLY|O_NONBLOCK ))==-1 ){
00327     printf("erreur d'ouverture du tube\n");
00328     return -1;
00329   } 
00330   lu = 1;
00331   while (lu > 0) {
00332     lu = read(fifo,&mes_lus,sizeof(struct message));
00333     if ((lu != sizeof(struct message)) && (lu != 0)) {
00334       printf("erreur de lecture dans le tube\n");
00335       return -1;
00336     }
00337   }
00338   close(fifo);
00339   interprete_commande(mes_lus);
00340   return 0;
00341 }
00342 
00343 /**
00344  * Interpreter les commandes envoyes par l'interface
00345  * \param structure message  contenant la commande ainsi que les arguments
00346  * \return
00347  * - -1 en cas d'erreur
00348  * - 0 sinon
00349  **/
00350 int  interprete_commande(message mes){
00351   switch(mes.commande){
00352   case LP:
00353     liste_process();
00354     break;
00355   case STDIN:
00356     modif_process(mes.int_opt,mes.ref);
00357     break;
00358   case LPT:
00359     printtp(mes.int_opt);
00360     break;
00361   case PPP:
00362     printpp(mes.int_opt);
00363     break;
00364   case PSIG:
00365     printsig(mes.int_opt);
00366     break;
00367   case SIG: 
00368     signal_proc(mes.int_opt2,mes.int_opt);
00369     break;
00370   default:
00371     perror("erreur de message\n");
00372     return -1;
00373   }
00374   return 0;
00375 }
00376 
00377 /**
00378  * Ecrit une chaine de caractere dans le tampon d'entree dun processus
00379  * \param numero du processus
00380  * \param chaine de carracteres
00381  * \return
00382  * - -1 en cas d'erreur
00383  * - 0 sinon
00384  **/ 
00385 int modif_process(int num_proc, char *ref){
00386   int i=0;
00387 
00388   while(ref[i] != '\0'){
00389     if(ecrire_stdin(num_proc, ref[i]) < 0){
00390       printf("impossible d'ecrire dans le tampon d'entree du processus N° : %d\n",num_proc);
00391     }
00392     i++;
00393   }
00394   return 0;
00395 }
00396 
00397 /**
00398  * Lister tous les processus actif
00399  * \return
00400  * - -1 en cas d'erreur
00401  * - 0 sinon
00402  **/
00403 int liste_process(){
00404   int i;
00405   mot_t mot;
00406   int etat;
00407   
00408   printf("PID\n");
00409   for(i=1; i<N_MAX_PROC+1;i++){
00410     if(lire_mot_mem(i, NUM_PAGE_META, mot) == -1){
00411       printf("erreur de lecture du mot du processus N° %d\n",i);
00412       return -1;
00413     }
00414     etat = lire_etat(mot);
00415     switch(etat){
00416     case E_MORT:
00417       printf("Processus N° %d mort\n", i);
00418       break;
00419     case E_ELIGIBLE: 
00420       printf("Processus N° %d eligible\n",i);
00421       break;
00422     case E_ZOMBI :    
00423       printf("Processus N° %d zombi\n",i);
00424       break;
00425     case E_SUSP:     
00426       printf("Processus N° %d suspendu\n",i);
00427       break;
00428     case E_ATT_FILS:
00429       printf("Processus N° %d attendant la mort d'un fils\n",i);
00430       break;
00431     case E_ATT_LECT: 
00432       printf("Processus N° %d attendant une fin de lecture\n",i);
00433       break;
00434     case E_ATT_ECRIT: 
00435       printf("Processus N° %d attendant une fin d'ecriture\n",i);
00436       break;
00437     default:
00438       printf("erreur etat non attendu\n");
00439       return -1;      
00440     }
00441   }
00442   return 0;
00443 }
00444 
00445 /**
00446  * Afficher la table des pages d'un processus
00447  * \param numero de processus
00448  * \return
00449  * - -1 en cas d'erreur
00450  * - 0 sinon
00451  **/
00452 int printtp(pid_t pid){
00453   mot_t mot;
00454   int num_page_tp;
00455   int i,j;
00456   char *tab;
00457 
00458   if(lire_mot_mem(pid, NUM_PAGE_META, mot) == -1){
00459     printf("Erreur de lecture du mot dans la page physique numero %d\n", pid);
00460     return -1;
00461   }
00462   tab = malloc(1);
00463   num_page_tp = (int)mot[3];
00464   for(i=0; i<3;i++){
00465     for(j=i*T_MAX_ZONES;j<(i+1)*T_MAX_ZONES;j++){
00466       if(lire_mot_mem(i,num_page_tp,mot) == -1){
00467         printf("Erreur de lecture du mot dans la page physique numero %d\n", j);
00468         return -1;
00469       } 
00470       if ((int)mot[2] == PP_RAM) {
00471         tab = realloc(tab,4);
00472         memcpy(tab ,"RAM",4);
00473       }
00474       else if ((int)mot[2] == PP_SWAP) {
00475         tab = realloc(tab,5);
00476         memcpy(tab,"SWAP",5);
00477       }
00478       else if ((int)mot[2] == PP_NULL) {
00479         break;
00480       }
00481       switch(i){
00482       case 0:
00483         printf("%d e  page de code :  %d en %s\n",j+1,(int)mot[3],tab);
00484         break;
00485       case 1:
00486         printf("%d e  page de donnee :  %d en %s\n",j+1,(int)mot[3],tab);
00487         break;
00488       case 2:
00489         printf("%d e  page de pile :  %d en %s\n",j+1,(int)mot[3],tab);
00490         break;
00491       default:
00492         printf("page inconnue\n");
00493         return -1;
00494       }
00495       printf("\n");
00496     }
00497   }
00498   free(tab);
00499   return 0;
00500 }
00501 
00502 /**
00503  * Ecris dans un fichier le contenue d'une page physique
00504  * \param numero de la page
00505  * \return
00506  * - -1 en cas d'erreur
00507  * - 0 sinon
00508  **/
00509 int printpp(int num){
00510   int i;
00511   int d;
00512   mot_t mot;
00513   if((d=open("table.mem",O_WRONLY|O_CREAT)) == -1){
00514     printf("erreur d'ouverture du fichier ou de creation\n");
00515     return -1;
00516   }
00517   for(i = 0; i < NMPPP; i++){
00518     if(lire_mot_mem(i,num, mot) == -1){
00519       printf("erreur de lecture du mot\n");
00520       return -1;
00521     }
00522     if(write(d,mot,4) == -1){
00523       printf("erreur d'ecriture dans le Fichier\n");
00524       return -1;
00525     }
00526     i++;
00527   }
00528   close(d);
00529   return 0;
00530 }
00531 
00532 /**
00533  * Fonction qui affiche les informations relatives aux signaux
00534  * \param pid : num du processus
00535  * \return  
00536  * - -1 en cas d'erreur inconnue
00537  * - 0  sinon
00538  */
00539 int printsig(int num_proc){
00540   mot_t mot;
00541   if(lire_mot_mem(num_proc,NUM_PAGE_META,mot) == -1){
00542     printf("erreur de lecture du mot N° de process : %d\n",num_proc);
00543     return -1;
00544   }
00545   if(SIFUNSIG(mot[0])){
00546     printf("Aucun signal attache au processus N° %d\n", num_proc);
00547     return 0;
00548   }
00549   else {
00550     if( SIFKILL(mot[0])){
00551       printf("Signal: Arme Fatale attache au processus N° %d\n", num_proc);
00552     }
00553     if( SIFMEM(mot[0])){
00554       printf("Signal: violation de memoire  attache au processus N° : %d\n", num_proc);
00555     }
00556     if( SIFSUSP(mot[0])){
00557       printf("Signal: suspension attache au processus N° %d\n", num_proc);
00558     }
00559     if( SIFREP(mot[0])){
00560       printf("Signal: de reprise attache au processus N° %d\n", num_proc);
00561     }
00562     if( SIFUSR1(mot[0])){
00563       printf("Signal: non definie attache au processus N° %d\n", num_proc);
00564     }
00565     if( SIFUSR2(mot[0])){
00566       printf("Signal: non defenie attache au processus N° %d\n", num_proc);
00567     }
00568     if( SIFINSTI(mot[0])){
00569       printf("Signal:  instruction illegale  attache au processus N° %d\n", num_proc);
00570     }
00571   }
00572   return 0;  
00573 }
00574 
00575 /**
00576  * Fonction qui affecte un signale a un processus
00577  * \param num_sig : num du signal
00578  * \param pid : num du processus
00579  * \return  
00580  * - -1 en cas d'erreur inconnue
00581  * - 0  sinon
00582  */
00583 int signal_proc(int num_sig, int pid){
00584   mot_t mot;
00585   if(lire_mot_mem(pid,NUM_PAGE_META,mot) == -1){
00586     printf("echec a la lecture du mot , processus N°%d\n", pid);
00587     return -1;
00588   }
00589   mot[0] = mot[0] | num_sig ;
00590   if(ecrire_mot_mem(pid,NUM_PAGE_META,mot) == -1){
00591     printf("echec de l'ecriture du mot , N° processus :%d\n",pid);
00592     return -1;
00593   }
00594   return 0;
00595 }

Généré le Sun Sep 29 22:47:22 2002 pour KSInu par doxygen1.2.16