Vous êtes sur la page 1sur 3

USTHB Année 2018/2019

Faculté d'Electronique et Informatique SYS02


Département Informatique L3 Acad A, B, C
Série N° 4
Gestion du processeur
Scheduling

ATTENTION : Comme il est très facile de faire des erreurs de programmations, vous
allez certainement créer des processus qui resteront en tâche de fond sans que vous le
sachiez. Lancez la commande top dans une fenêtre toujours visible pour vérifier si un
processus non désiré tourne encore.

Exercice 1 Programmation des signaux SIGINT


Lancez un éditeur de texte (kwrite), puis écrire le programme suivant

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

//Fonction appelée lorsque CTRL-C (signal SIGINT) est envoyé à un processus


Void signal_callback_handler(int signum)
{
printf("Capture du signal %d\n",signum);
exit(signum);
}
int main()
{
//Définir un handler qui traitera le signal SIGINT capture
signal(SIGINT, signal_callback_handler);
while(1)
{
       printf("Program processing stuff here.\n");
sleep(1);
}
return EXIT_SUCCESS;
}

1. Compiler ce programme et l’exécuter.


2. Par quel moyen arrêter le processus lancé ?
3. Transformer ce programme en processus fils lancé par un processus père principal. Le
processus père doit arrêter son fils après une attente de 60 secondes. Pour cela, utiliser la
primitive :
int kill(pid_t pid, int signal);

Exercice 2 (Politique Round Robin)


1. Créer un programme scheduler qui va lancer 10 fils. Chaque fils exécute le code suivant :
– se met en attente d’un signal
– lance une boucle infinie affichant le numéro du fils toutes les secondes
Après avoir créé les fils, le père :

1/3
– envoie SIGSTOP à tous les fils.
– réveille un fils pendant 5 secondes (en se basant sur l’ordre de lancement des fils), en
utilisant les signaux SIGCONT et SIGSTOP.

2. Utiliser le programme scheduler écrit avec 3 fils faisant chacun les calculs suivants :
- 1er fils : boucle qui lit 100 entiers et affiche son factoriel.
- 2nd fils : boucle qui lit 100 chaînes de caractères et affiche si la chaîne est un palindrome.
-3ième fils : boucle imbriquée qui lit 100 entiers et pour chaque entier N, lit 100 autres
entiers M et affiche le résultat de la division du factoriel de N sur M.
Ajouter la vérification de la fin du processus pour l’enlever de la liste des processus fils prêts
à exécuter. Pour cela, utiliser la primitive suivante :
pid_t waitpid(pid_t pid, int *status, intoptions) avec l’option WNOHANG

Exercice 3 (Création de Threads)


1°) A partir d’une console, lancer l’éditeur de texte kwrite. Ecrire le programme sivant :
// thread.c
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h> // fork
#include <stdlib.h> // exit

void* thread1(void* n)
{
printf("Début Thread\n");
sleep(5);
printf("Thread : numéro : %d\n", pthread_self());
printf("Thread : Fin Thread\n");
pthread_exit(NULL);
}

int main()
{
pthread_t thr;

if (fork()==0)
{
// debut fils
printf("Début fils \n");
printf("Fils : pid=%d, ppid=%d\n", getpid(), getppid());
printf("Fils : numéro thread fils : %d\n", pthread_self());
printf("Fils : Fin Fils \n");
exit(0);
// Fin fils
}
// Suite du père
printf("Pere : pid=%d, ppid=%d\n", getpid(), getppid());
printf("Pere : Lancement Thread \n");
int r1=pthread_create(&thr,NULL,thread1,NULL);
sleep(2);
printf("Pere : numéro thread main : %d\n", pthread_self());
printf("Pere : Attente Fin thread %d \n", thr);
pthread_join(thr,NULL);
printf("Pere : Fin thread \n");
printf("Pere : Fin Pere \n");
return(0);

2/3
}
Compilez et exécutez.
Note : Pour compiler, il est nécessaire de préciser l’utilisation de la librairie qthreads. Pour
cela, utiliser la commande suivante :
gcc thread.c –o thread -lqthreads
Pour exécuter, il suffit de lancer ./thread
2°) Modifier ce programme de telle manière à créer deux threads dont le deuxième attend la
fin du premier (Montrer cela par des affichages).

Compléments d'information

Manipulation de threads
Les threads partagent le même espace d’adressage que leurs parents. Chaque thread peut
accéder aux varaibles globales du programme qui le crée. Cependant, comme les thrteads se
déroulent concuremment, on retrouve le problème d’accès concurent à une variable partagée
entre plusieurs threads.
Un thread est identifié par une variable de type pthread_t (entier long positif).
1. L’appel système pthread_create(……) crée un thread et démarre son execution :
Int pthread_create(
pthread_t* thread, // numéro identifiant le thread créé
pthread_attr_t* attr, // attributs ou NULL par défaut
void* (*fn) (void* arg), // fonction à exécuter (pointeur de fonction)
void* arg // arguments de la fonction
) ;
2. La fonction int pthread_exit (void* retour) termine le thread en cours d’exécution. Une
valeur de retour peut être récupérée par un autre thread par l’intermédiaire de la fonction :
int pthread_join(pthread_t thread, void** retour) ;
NULL en paramètre indique une absence de valeur de retour. Si le thread est détruit avant sa
fin normale par un autre thread, la valeur de retour est PTHREAD_CANCEL.
3. D’autres fonctions :
int pthread_detach(pthread_t thread) : récupérer ses ressources dès sa fin.
pthread_t pthread_self : fournit l’identifiant du thread courant.
int pthread_cancel(pthread_t thread) : détruit le thread.
Int pthread_join (pthread_t thread, void **retval): attend la fin d’un autre thread.

3/3