IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Exercice : Environnement multithread


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 8
    Par défaut Exercice : Environnement multithread
    Bijour bijour les gens,

    je vous expose mon prôbleme:
    J'ai un sujet de projet qui me pose quelques difficultés. Pour tout dire, je suis completement paumé, limite en train de taper mon pc de frustration.

    Bon, en voila le sujet:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
     
    Sujet de projet - Système IN115
     
    Le but de ce projet est de réaliser un environnemet multithread en espace utilisateur. Le développement de deux programmes faisant usage de cet environnement est également demandé.
     
    Les programmes doivent être écrits en langage C, et doivent faire usage des appels système UNIX que vous connaissez. L'utilisation de tout autre environnement multithread, tel que les threads POSIX, est interdite.
     
    Ce projet doit être réalisé en binômes.
    Description générale
     
    Comme son nom l'indique, un environnement multithread en espace utilisateur fonctionne dans un environnement de processus. L'utilisateur a donc toute latitude pour programmer ses threads à sa manière. Il n'a aucune prise sur les autres processus du système, et encore moins sur le système lui-même.
     
    Un contexte de thread se limite à la valeur des registres du processus, et à une pile de thread. Le basculement d'un thread vers un autre par l'ordonnanceur se limite simplement à sauvegarder le contenu des registres (ce qui inclut le pointeur de pile) dans une zone mémoire réservée du thread appelant, et à restaurer le contenu des registres tel qu'ils étaient lorsque ce second thread avait précédemment fait appel à l'ordonnanceur.
     
    Le pointeur de pile, ainsi que le compteur ordinal étant eux-mêmes des registres, le fait de modifier leur valeur permet de changer la pile courante, et de sauter l'exécution vers la position définie par le compteur ordinal du nouveau contexte. Ainsi, un thread interrompu peut reprendre son exécution exactement dans l'état où il était au moment de l'appel à l'ordonnanceur.
    Indications
    Contextes de thread
     
    Sous UNIX, la gestion de contextes s'effectue à l'aide de l'API ucontext, disponible en utilisant le fichier d'en-tête ucontext.h.
     
    Cette API contient entre autres les structures de données et fonctions suivantes :
     
    typedef struct {
    	void 	*ss_sp;		/* adresse de base de la pile */
            int	ss_flags;	/* flags */
            size_t	ss_size;	/* taille de la pile en octets */
    } stack_t;
     
    typedef struct ucontext {
            struct ucontext *uc_link;
            sigset_t         uc_sigmask;
            stack_t          uc_stack;
            mcontext_t       uc_mcontext;
            ...
    } ucontext_t;
     
    void makecontext(ucontext_t *ucp, void *func(), int argc, ...);
    int swapcontext(ucontext_t *oucp, ucontext_t *ucp);
    int getcontext(ucontext_t *ucp);
    int setcontext(const ucontext_t *ucp);
     
        * setcontext permet de définir le contexte courant en utilisant le contenu de la structure pointée par ucp. Il en résulte un saut vers la position désignée par le compteur ordinal.
        * getcontext permet de récupérer le contexte courant. On peut donc revenir à la position qui suit directement l'appel à getcontext, en fournissant le contexte obtenu à setcontext.
        * swapcontext effectue à la fois la sauvegarde du contexte courant et le basculement vers un autre contexte.
        * makecontext est une fonction qui permet de construire un contexte pour un nouveau thread. On part en principe d'un contexte déjà existant (obtenu avec getcontext), et on lui associe une nouvelle pile et une fonction à appeler, comme dans l'exemple ci-dessous :
     
          /* taille de la pile du nouveau thread, ici 64 ko */
          #define STACK_SIZE 65536
     
          /* contexte où l'on va sauvegarder le contexte courant avant le saut vers le
           * nouveau contexte */
          ucontext_t ici;
     
          /* obtenir le contexte courant */
          ucontext_t labas;
          getcontext(&labas);
     
          /* taille de la pile associée au thread */
          labas.uc_stack.ss_size = STACK_SIZE;
     
          /* le bloc mémoire correspondant à la pile */
          labas.uc_stack.ss_sp = malloc(STACK_SIZE);
     
          /* on ignore les flags */
          labas.uc_stack.ss_flags = 0;
     
          /* le contexte sur lequel basculer quand la fonction_thread sera terminée.
           * Idéalement, la fonction à exécuter devra libérer les ressources allouées
           * pour le thread, comme la pile, et exécuter l'ordonnanceur pour poursuivre
           * l'exécution d'un autre thread.
           */
          labas.uc_link = &contexte_fin_thread;
     
          /* modification du contexte en donnant comme point d'entrée la fonction
           * fonction_thread, prenant n arguments : argument1, ... , argumentn
           */
          makecontext(&labas, &fonction_thread, n, &argument1, ..., &argumentn);
     
          /* sauvegarde du contexte courant, et basculement vers le nouveau contexte */
          swapcontext(&ici, &labas);
     
    L'API multi-thread
     
    Les appes de votre API multi-thread devront ressembler à ceux que vous connaissez dans les threads POSIX.
     
    Vous définirez les fonctions suivantes :
     
        * gestion des threads
              o int thread_create(thread_t * thread, void *(*start_routine)(void *), void * arg);
                qui crée un thread te place son identifiant dans la variable pointée par thread.
              o int thread_join(thread_t th, void **thread_return);
                qui attend la fin de l'exécution du thread th, et place sa valeur de retour dans la variable pointée par thread_return.
              o int thread_yield(void);
                qui appelle l'ordonannceur pour basculer l'exécution d'un thread à un autre.
        * gestion des mutex
              o int thread_mutex_init(mutex_t *mutex);
                qui initialize un mutex (une allocation statique est également possible en affectant une constante THREAD_MUTEX_INITIALIZER à la déclaration d'un mutex)
              o int thread_mutex_lock(mutex_t *mutex);
                qui verrouille un mutex
              o int thread_mutex_unlock(mutex_t *mutex);
                qui déverrouille un mutex
        * gestion des conditions
              o int thread_cond_init(cond_t *cond);
                qui initialise une variable de condition
              o int thread_cond_signal(cond_t *cond);
                qui relance un des threads bloqués en attente de la condition cond
              o int thread_cond_broadcast(cond_t *cond);
                qui relance tous les threads bloqués en attente de la condition cond
              o int thread_cond_wait(cond_t *cond, mutex_t *mutex);
                qui déverrouille atomiquement le mutex et attend que la variable de condition cond soit signalée;
     
    Vous devrez définir les types thread_t, mutex_t, et cond_t. Par exemple, comme un thread ordonnancé peut avoir plusieurs états (en attente, bloqué sur un mutex, bloqué sur un thread_join, ...), doit également posséder son propre contexte, et possède très certainement d'autres attributs, vous pourriez définir un structure de thread et définir le type thread_t comme un pointeur vers cette structure.
    L'ordonnanceur
     
    L'ordonnanceur est de type coopératif, c'est-à-dire que les threads lui font volontairement appel pour basculer de l'exécution d'un thread à un autre, contrairement à un ordonnanceur préemptif, qui est exécuté à intervalles réguliers, même si les threads ne lui font pas appel. Des situations de conditions de concurrence pouvant être induites par la préemption sont inexistantes dans un contexte de threads coopératifs.
     
    Nous l'avons vu auparavant, l'appel à thread_yield pour basculer de l'exécution d'un thread à un autre est relativement peu utilisé directement par les programmes utilisateur multi-thread. Cet appel est plutôt réservé aux fonctions de bibliothèques compatibles avec l'environnement multi-thread. Par exemple, la gestion de mutex peut s'effectuer en vérifiant la valeur d'une variable partagée, et tant que cette valeur est non-nulle, on boucle en effectuant des appels à thread_yield.
     
    La stratégie d'ordonnancement sera un simple round-robin.
     
    Votre ordonnanceur doit gérer des listes de threads : liste des threads bloqués, prêts, en attente d'un thread_join, d'un mutex, etc. À tout moment, un thread est dans une et une seule liste seulement.
    Entrées/sorties avec read et write
     
    Vos programmes seront capables d'effectuer des entrées/sorties avec des appels comparables au read et au write. Vous devrez tenir compte du fait que read et write peuvent être bloquants : cela risque donc de bloquer tout le processus sans possiblité de basculer l'exécution vers un autre thread. Vous devrez donc définir deux fonctions read2 et write2, semblables de l'extérieur à read et write, mais qui effectueront un test de disponbilité de données (cf. appel système select) sur les descripteurs de fichiers concernés avant de lancer une lecture ou une écriture (ou sinon, un basculement de thread).
     
    De cette manière, vos threads seront normalement capables de faire des accès disques non bloquants, et même de communiquer entre eux par l'intermédiaire de tubes !
     
    Endormissement de threads (optionnel)
     
    Si vous vous en sentez le courage, vous pouvez réimplémenter le sleep, sachant que le thread faisant appel à votre fonction ne devra pas bloquer les autres, et que plusieurs threads auront la possiblité de faire des appels à sleep en même temps.
    Travail demandé
    Le programme
     
        * Vous devez programmer le projet en langage C.
        * Vous incluerez à votre projet un fichier Makefile, afin d'automatiser la compilation par une simple commande make. Le Makefile doit également inclure une cible clean, afin de nettoyer le répertoire des fichiers générés.
        * Toute la configuration du programme (valeur des constantes, éventuellement la compilation conditionnelle) devra pouvoir être effectuée en ne modifiant que le fichier Makefile.
        * Prenez un soin particulier pour l'efficacité de votre programme :
              o pas de code inutile ;
              o pas de copier/coller de code (quelques lignes code servant plusieurs fois dans le programme doivent être intégrées dans une fonction) ;
              o prenez un soin particulier pour l'efficacité des entrées/sorties : faites un usage optimal de buffers de fichiers.
        * Suivez correctement les recommandations pour les projets de votre annexe de cours.
     
    Les tests
     
    Vous testerez votre bibliothèque de threads à l'aide de deux programmes (ou trois si vous avez réimplémenté le sleep) :
     
       1. Un algorithme de tri de type quicksort ou tri rapide. Au lieu d'effectuer des appels récursifs, l'algorithme créera des threads pour le tri des sous-tableaux.
          Vous implémenterez votre tri avec un programme d'exemple triant un tableau de 1000 valeurs aléatoires comprises entre 0 et 10000.
       2. Un programme créant un chaîne de 10 threads communiquant par 9 tubes. Le premier thread lit les caractères lus sur l'entrée standard, les écrit à l'entrée du tube de sortie, puis les caractères sont relayés par les tubes de thread en thread, jusqu'au dernier, qui les écrira sur la sortie standard.
       3. Si vous avez réimplémenté le sleep, vous ferez un programme qui lance une dizaine de threads effectuant chacun une attente différente entre 1 et 10 secondes, et montrant que les threads se réveillent bien au moment voulu.
     
    Le rapport
     
    Votre travail devra être accompagné d'un rapport, dans un format de texte courant (PostScript, Acrobat (pdf), OpenDocument, ...), décrivant votre travail, les problèmes posés et les réponses que vous y avez apportées.
     
    Vous attacherez une importance particulière pour montrer que ce que vous avez réalisé effectue bien ce qui était demandé : donnez les algorithme utilisés, les mécanismes employés, etc. Justifiez également vos choix pour les structures de données.
     
    Expliquez comment les allocations faites au moment de la création d'un thread sont bien libérées à la terminaison de ce même thread.
     
    Le rapport n'a pas besoin d'être volumineux, allez à l'essentiel. Merci de ne pas inclure l'intégralité du code dans le rapport ; n'incluez que des parties de code, et seulement si elles sont nécessaires dans vos explications.
    Remise du projet
     
    La date de remise du projet est fixée au lundi 14 janvier 2008, à 23h59 au plus tard.


    Voila, désolé pour le pavé, mais si vous aviez quelques pistes (ou des tickets restaurants), je suis preneur.

  2. #2
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Bonne année et bienvenu sur les forums de DVP

    Au lieu de taper ton PC qui n'y est pour rien, tu ferais mieux d'indiquer où tu en es de ton projet, ce que tu as déjà fait et sur quoi tu bûtes.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 8
    Par défaut
    en fait, je bute sur pas mal de chose, et je n'en suis pas tres tres loin


    Déja, les intitulés de fonctions a coder prennent souvent en entrée un "thread_t", équivalent au pthread_t, mais javoue ne pas savoir ce qui ce cache la derriere.

    Mais sinon, ce qui m'embete surtout, c'est une vision globale des choses, car les context et tout ca, je n'en n'avais jamais entendu parlé avant de lire ce sujet

  4. #4
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par cerby Voir le message
    en fait, je bute sur pas mal de chose, et je n'en suis pas tres tres loin


    Déja, les intitulés de fonctions a coder prennent souvent en entrée un "thread_t", équivalent au pthread_t, mais javoue ne pas savoir ce qui ce cache la derriere.

    Mais sinon, ce qui m'embete surtout, c'est une vision globale des choses, car les context et tout ca, je n'en n'avais jamais entendu parlé avant de lire ce sujet
    On te balance un exo sur un sujet que tu n'as jamais vu en cours ? C'est quoi encore cette école ?

    http://emmanuel-delahaye.developpez.com/pthreads.htm

Discussions similaires

  1. OperationContext.Current dans un environnement multithread
    Par zitoun dans le forum Windows Communication Foundation
    Réponses: 1
    Dernier message: 09/01/2013, 14h43
  2. Compteurs en environnement multithread
    Par bartinou dans le forum Langage
    Réponses: 3
    Dernier message: 16/08/2011, 11h38
  3. Singleton en environnement Multithread
    Par alladdin dans le forum Langage
    Réponses: 22
    Dernier message: 13/07/2011, 16h41
  4. Réponses: 20
    Dernier message: 09/01/2011, 19h02
  5. lock de fichiers en environnement multithreadé
    Par Pi2 dans le forum Entrée/Sortie
    Réponses: 1
    Dernier message: 05/09/2007, 18h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo