// Programme permettant de tester les politiques d'ordonnancement et // surtout de mesurer différents temps #include #include #include #include #include #include #include #include struct timeval startTime; struct timeval stopTime; struct sched_param sp; #define FATAL(msg) {\ char m[128]; \ sprintf(m, "%s in %s:%d:%s", msg, __FILE__, __LINE__, __func__); \ perror(m); \ abort(); \ } /**********************************************************************/ /* Nombre de fois qu'on doit effectuer une operation : */ /* - Sur machine native, mettre 1000000 */ /* - Sur machine virtuelle, mettre 1000 */ /**********************************************************************/ #define NBFOIS 1000 /**********************************************************************/ /* Affiche message suivie de la duree de temps ecoule entre pstart et */ /* pstop */ /**********************************************************************/ void afficherDuree( char *msg, struct timeval *pStart, struct timeval *pStop) { struct timeval diffTimeval; /* NB: timersub (et timeradd) sont des macros declarees dans */ /* */ timersub(pStop, pStart, &diffTimeval); (void)printf("%s = %8d.%06d s\n", msg, (int)diffTimeval.tv_sec, (int)diffTimeval.tv_usec); } /**********************************************************************/ /* Code execute par le processus fils */ /**********************************************************************/ void codeFils() { int i; double s,x; struct timespec ts; /*********************************/ /* Contribution a la 4eme mesure */ /*********************************/ for (i=NBFOIS ; i>0 ; i--) { /* Instruction(s) pour céder le processeur ? */ if (sched_yield()<0) { FATAL("sched_yield"); } } /**********************************************/ /* Contribution a la 5eme (et la 6eme) mesure */ /**********************************************/ if (gettimeofday(&startTime,NULL) < 0) { FATAL("gettimeofday"); } /* Instruction(s) pour adopter une politique d'ordonnancement SCHED_RR */ /* avec une priorité statique de 1 ? */ sp.sched_priority = 1; if (sched_setscheduler(0,SCHED_RR,&sp) < 0) { FATAL("sched_setscheduler"); } s = 0; for (i=0 ; i<5*NBFOIS ; i++) { x = sin(3.141592654 * s); x = cos(3.141592654 * s); x = tan(3.141592654 * s); s += 0.1; } s = x; // Ligne pour eviter un warning du compilateur // pour signaler que x n'est jamais lue if (gettimeofday(&stopTime,NULL) < 0) { FATAL("gettimeofday"); } afficherDuree("Temps CPU intensif", &startTime, &stopTime); /* Instruction(s) pour mettre dans la variable ts le quantum de temps ? */ if (sched_rr_get_interval(0,&ts) < 0) { FATAL("sched_rr_get_interval"); } /* Instruction(s) pour imprimer le contenu de la variable ts ? */ printf("Valeur de sched_rr_get_interval (pour le fils) = %8d.%09d s (attention Nanosecondes !)\n", (int)ts.tv_sec, (int)ts.tv_nsec); } /**********************************************************************/ /* Code execute par le processus pere */ /**********************************************************************/ void codePere() { int i; struct timeval startTime5; struct timeval stopTime5; struct timeval startTime6; struct timeval stopTime6; char msg[128]; /***************/ /* 4eme mesure */ /***************/ if (gettimeofday(&startTime,NULL) < 0) { FATAL("gettimeofday"); } for (i=NBFOIS ; i>0 ; i--) { /* Instruction(s) pour céder le processeur ? */ if (sched_yield()<0) { FATAL("sched_yield"); } } if (gettimeofday(&stopTime,NULL) < 0) { FATAL("gettimeofday"); } /***************/ /* 5eme mesure */ /***************/ /* Instruction(s) pour céder le processeur ? */ /* Question : pourquoi a-t-on besoin de cette instruction, ici ? */ /* Reponse : ce premier sched_yield permet au fils de changer de */ /* politique de scheduling. Une fois qu'il l'aura fait, il nous */ /* rendra la main. */ if (sched_yield()<0) { FATAL("sched_yield"); } if (gettimeofday(&startTime5,NULL) < 0) { FATAL("gettimeofday"); } /* Instruction(s) pour céder le processeur ? */ /* Question : pourquoi a-t-on besoin de cette instruction, ici ? */ /* Reponse : quand le fils a repris la main, il a changé sa politique */ /* d'ordonnancement. Donc, il s'est remis dans la file d'attente */ /* Donc le père a repris la main ! Il faut donc qu'il la rende au fils. */ if (sched_yield()<0) { FATAL("sched_yield"); } if (gettimeofday(&stopTime5,NULL) < 0) { FATAL("gettimeofday"); } /***************/ /* 6eme mesure */ /***************/ /* Instruction(s) pour que le père ait une priorité statique de 2 */ sp.sched_priority = 2; if (sched_setparam(0,&sp) < 0) { FATAL("sched_setparam"); } if (gettimeofday(&startTime6,NULL) < 0) { FATAL("gettimeofday"); } usleep(1000000); if (gettimeofday(&stopTime6,NULL) < 0) { FATAL("gettimeofday"); } /* Affichage des mesures 4, 5, 6 */ sprintf(msg, "Temps mesure 4 = Temps pour %d ? sched_yield", NBFOIS); afficherDuree(msg, &startTime, &stopTime); afficherDuree("Temps mesure 5 = Estimation sched_rr_get_interval", &startTime5, &stopTime5); afficherDuree("Temps mesure 6 = Estimation préemption par process qui a dormi 1 seconde", &startTime6, &stopTime6); } /**********************************************************************/ /* Programme principal */ /**********************************************************************/ int main(int argc, char* argv[]) { int i; int status; char msg[128]; if (argc != 1) { fprintf(stderr, "USAGE = polOrdo"); return EXIT_FAILURE; } /* Instruction(s) pour que le père ait une priorité statique de 1 */ /* avec une politique d'ordonnancement FIFO ? */ sp.sched_priority = 1; if (sched_setscheduler(0,SCHED_FIFO,&sp) < 0) { FATAL("sched_setscheduler"); } /***************/ /* 1ere mesure */ /***************/ if (gettimeofday(&startTime,NULL) < 0) { FATAL("gettimeofday"); } for (i=NBFOIS ; i>0 ; i--) { struct timeval intermediateTime; if (gettimeofday(&intermediateTime,NULL) < 0) { FATAL("gettimeofday"); } } if (gettimeofday(&stopTime,NULL) < 0) { FATAL("gettimeofday"); } sprintf(msg, "Temps mesure 1 = Temps pour %d ? gettimeofday", NBFOIS); afficherDuree(msg, &startTime, &stopTime); /***************/ /* 2eme mesure */ /***************/ if (gettimeofday(&startTime,NULL) < 0) { FATAL("gettimeofday"); } for (i=NBFOIS ; i>0 ; i--) { /* Instruction(s) pour que le père ait une priorité statique de 1 */ /* avec une politique d'ordonnancement FIFO ? */ sp.sched_priority = 1; if (sched_setscheduler(0,SCHED_FIFO,&sp) < 0) { FATAL("sched_setscheduler"); } } if (gettimeofday(&stopTime,NULL) < 0) { FATAL("gettimeofday"); } sprintf(msg, "Temps mesure 2 = Temps pour %d ? sched_setscheduler", NBFOIS); afficherDuree(msg, &startTime, &stopTime); /***************/ /* 3eme mesure */ /***************/ if (gettimeofday(&startTime,NULL) < 0) { FATAL("gettimeofday"); } switch (/* Instruction(s) pour démarrer un fils ? */fork()) { case -1: /* Instruction(s) qui vous semble(nt) la (ou les) plus intelligente(s) */ /* au vu du contexte ? */ FATAL("fork"); break; case 0: /* Instruction(s) qui vous semble(nt) la (ou les) plus intelligente(s) */ /* au vu du contexte ? */ codeFils(); break; default: if (gettimeofday(&stopTime,NULL) < 0) { FATAL("gettimeofday"); } afficherDuree("Temps mesure 3 = Temps pour fork", &startTime, &stopTime); /* Instruction(s) qui vous semble(nt) la (ou les) plus intelligente(s) */ /* au vu du contexte ? */ codePere(); wait(&status); } return EXIT_SUCCESS; }