Vous êtes sur la page 1sur 6

Ecole Nationale des Ingénieurs de Tunis

Filière : 2ème année Informatique


Module: Systèmes d’exploitation
Fiche de Travaux Pratiques n° 2

Thème: Programmation Multithread

1.Objectif

Il s'agit de d’effectuer des premiers pas avec la programmation Multithread en C, en utilisant la bibliothèque
pthread et d’étudier des schémas « classiques » de synchronisation.

2.Compilation

Pour utiliser la bibliothèque pthread, le code doit contenir : #include <pthread.h>

L’édition de lien doit se faire avec l'option « -pthread », c’est-à-dire pour compiler le
programme « test.c » il faut taper : gcc -o test -pthread test.c

3.Manipulation des threads

Créer un thread

Pour créer un thread,on commence par déclarer une variable le représentant. Celle-ci
sera de type pthread_t (unsigned long int).

Ensuite, pour créer la tâche elle-même, il suffit d'utiliser la fonction :

int pthread_create (

pthread_t * thread, // pointeur vers l'identifiant du thread

pthread_attr_t * attr, // attributs du thread, généralement NULL

void *(*start_routine) (void *), // pointeur vers la fonction à exécuter dans le thread

void *arg // argument à passer au thread

);

La fonction renvoie une valeur de type int : 0 si la création a été réussie ou une autre
valeur si il y a eu une erreur.

1
pthread_create( thread, attribut, routine, argument ): Créer d'un thread. Le nouveau
flot d'exécution démarre en se branchant à la routine spécifiée. Cette routine reçoit
l'argument prévu.

Autres fonctions

pthread_exit( résultat ) : termine l'exécution du thread et renvoie un résultat.


pthread_join( thread, résultat ): Attendre la terminaison d'un autre thread.
pthread_kill( thread, nu_du_signal ): Envoyer un signal (UNIX) à un thread. C'est un
moyen dur pour tuer un thread. Il existe des méthodes plus conviviales.
sched_yield(): Abandonner le CPU pour le compte d'un autre thread (ou un autre
processus).

4.Travail demandé

Exercice 1:
#include <stdlib.h>

#include <stdio.h>

#include <pthread.h>
 

void* maFonction(void* data);  

int main()

    int i;

    pthread_t thread;// On crée un thread

    pthread_create(&thread, NULL, maFonction, NULL); 

    for(i=0 ; i<500 ; i++)

        printf("1");

    printf("\n");

    pthread_join(thread, NULL);

    return 0;

2
  

void* maFonction(void* data)

    int i;

    for(i=0 ; i<500 ; i++)

        printf("2");

    printf("\n");

    return NULL;

Compiler et exécuter ce code. Expliquer le résultat affiché.

Exercice 2:
#include <pthread.h>

#include <stdio.h>

void * run(void * arg)

int i;

for(i=0;i<10;i++){

printf("t1 %d \n", i);

sleep(1);

return NULL;

3
int main(void)

pthread_t t1;

pthread_create(&t1, NULL, run, NULL);

printf("prog principal \n");

pthread_join(t1,NULL);

printf("Fin des threads \n");

1. Compiler et exécuter ce code.

2. Combien de Threads sont créés suite à l'exécution de ce code.

3. Si on supprime la commande pthread_join(t1,NULL), qu'est ce qui se passe ?

4. Garder la commande pthread_join(t1,NULL), et créer un deuxième thread


exécutant une fonction run2() qui fait un sleep de 2 secondes. qu'est ce qui se
passe ?

Exercice 3:

Écrire un programme qui permet de créer un thread qui lit des caractères au clavier et
les passe à un autre thread qui se charge de les afficher. Il faut noter que le thread
principal (le père) se charge de la création de ses fils et de l'attente de leur mort. Cette
disparition est programmée à l'arrivée du caractère "F".

4
Exercice 4:

Soit le programme suivant de calcul du nième nombre de Fibonacci :

#include <stdlib.h>

#include <stdio.h>

int fib (int n)

  if (n<2) return n ;

  else {

    int x, y ;

    x = fib (n­1) ; 

    y = fib (n­2) ;

    return x + y ; 

  }

int main (int argc, char *argv[])

  int n, res ;

  n = atoi (argv[1]) ;

  res = fib (n) ;

  printf ("Fibo (%d) = %d\n", n, res) ;

  exit (0) ; 

5
1. On veut accélérer l'exécution de ce code à l'aide des threads. L'idée est d'attacher
un thread à chacune des instances de la fonction fib(). On construit ainsi un arbre
de threads. Avant de retourner son résultat, un thread attend que ses deux fils
aient terminé.

2. On propose d'améliorer la solution précédente de la manière suivante : plutôt que


de déclencher un thread alors que la valeur a déjà été produite auparavant par un
autre thread, on récupère cette valeur. Pour cela, on garde les résultats
intermédiaires produits dans un tableau partagé entre les threads. (Les éléments
de ce tableau sont par exemple initialisés à la valeur INCONNUE pour dénoter que
la valeur n'a pas encore été calculée.)

#define INCONNUE -1 "F".