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

Langage C++ Discussion :

Les threads ( question )


Sujet :

Langage C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 82
    Par défaut Les threads ( question )
    Bonjour,

    J'aimerai connaître très précisément les changements lorsqu'un nouveau thread démarre, après par exemple l'appel de la fonction "CreateThread".

    La question semble sans doute un peu vague, mais ce sont mes connaissances sur le sujet qui le sont aussi. D'où une question vague.

    Merci par avance

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Effectivement, la question est vague et donc ma réponse sera générale.

    Déjà, tu peux regarder sur Wiki pour de l'info générale : http://fr.wikipedia.org/wiki/Processus_l%C3%A9ger

    Pour définir un thread, il fdaut d'abord définir un processus. Le lancement d'un programme (double clic sur un exe par exemple) correspond à la création d'un processus. Un processus, c'est de l'espace mémoire adressable par ce processus (le tas, la pile, les variables globales) et un thread principal (ou unité d'exécution) dont le point d'entrée en C et C++ correspond à la fonction main() ou WinMain() pour les programmes graphiques Windows. Pour info, il y a beaucoup de choses de choses qui sont faites par le loader de processus avant d'arriver à la fonction main() ou WinMain().

    Une fois que ton programme se déroule, tu peut créer autant de thread que tu veux (aux ressources près de la machine quand même) avec entre autre la fonction CreateThread(). Cette fonction va définir une autre unité d'exécution qui va démarrer à partir du point d'entrée (c'est une fonction) que tu spécifies. Ce thread se termine lorsqu'il quitte la fonction définie comme point d'entrée du thread.

    Ensuite, le système va donner du temps CPU à chacun des threads. Les 2 thread s'exécuteront simultanément et pourront faire 2 choses différentes en parallèle. C'est ce qui va donner une certaine illusion de multi tâches. Un thread pouura gérer l'interface Homme - Machine alors que k'autre thread pourra charger un fichier volumineux et que le 3eme thread pourra gérer tous les accès réseau.

    Il faut bien voir que tout l'espace mémoire créé et accessible par le thread principal est aussi accessible par les autres threads. C'est la grosse différence entre thread et processus, 2 processus ne partagent pas leur espace mémoire alors que 2 thread d'un même processus ont le même espace mémoire.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 82
    Par défaut
    Merci pour cette explication claire.

    Néanmoins, j'aimerai aller plus loin dans l'étude.

    Tu dis qu'à un processus correspond une pile.

    c'est de l'espace mémoire adressable par ce processus (le tas, la pile, les variables globales) et un thread principal (ou unité d'exécution)
    Hors il me semblait avoir compris durant mes recherches que une pile correspond à un thread.

    Donc il y aurait autant de piles que de thread non?

    Sinon je ne vois pas comment s'organise la gestion des instructions si plusieurs thread se mélangent dans la même pile.

    Deuxième question qui me vient à l'esprit, comment la mémoire utilisé par le nouveau thread ( pour les variables locales ) va être gérée? L'os s'occupe-t-il tout seul d'allouer une nouvelle section dans la mémoire du processus en cours?

    Pour préciser ma question voici où je bloque :

    Lorsqu'on lance notre exécutable, le loader lit l'en tête du fichier. Il alloue un espace mémoire à noter application, puis il charge dans cette espace, les différentes section qu'il aura trouvé dans notre en tête ( .text, .data, ... ).
    Il va également charger les différentes Dlls contenant les fonctions importées par l'application.
    Ensuite si dans notre application on invoque un nouveau thread, qu'est ce qui se produit exactement? Va-t-il y avoir une nouvelle section chargée?

  4. #4
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Citation Envoyé par klakman Voir le message
    Hors il me semblait avoir compris durant mes recherches que une pile correspond à un thread.

    Donc il y aurait autant de piles que de thread non?
    Oui, tu as raison, ce détail m'avait échappé. La création d'un thread créé aussi une pile pour ce thread.

    Citation Envoyé par klakman Voir le message
    Lorsqu'on lance notre exécutable, le loader lit l'en tête du fichier. Il alloue un espace mémoire à noter application, puis il charge dans cette espace, les différentes section qu'il aura trouvé dans notre en tête ( .text, .data, ... ).
    Il va également charger les différentes Dlls contenant les fonctions importées par l'application.
    Ensuite si dans notre application on invoque un nouveau thread, qu'est ce qui se produit exactement? Va-t-il y avoir une nouvelle section chargée?
    Non, dans le cas de plusieurs thread, il y a partage des sections de données, elles ne sont pas rechargées. C'est la grosse différence entre thread et processus.

    Cela as bien sur des avantages et des inconvénients :
    • Le context switching des thread est plus rapide que pour des processus (il y a moins de choses à changer).
    • La programmation multi thread est plus délicate que la programmation multi processus (il faut protéger les données lorsque 2 thread peuvent avoir un accès concurrent sur ces données)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 82
    Par défaut
    Merci pour cette info.

    Une dernière chose qui m'échappe pour le moment.

    il faut protéger les données lorsque 2 thread peuvent avoir un accès concurrent sur ces données
    Tu parles bien de sémaphores?
    Qui permet ( dîtes moi si je me trompe ) de bloquer tout autres threads nécessitant un accès à une zone mémoire, pendant qu'un thread exécute ses actions dessus.

    Si non, à quel type de protection fais-tu allusion? Peut-il y avoir des protections qui réservent un espace mémoire à un unique thread?

  6. #6
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Oui, tu as raison, ce détail m'avait échappé. La création d'un thread créé aussi une pile pour ce thread.
    Chaque thread a sa propre pile, son propre contexte d'exécution (ce qui inclus l'affinité processeur, la priorité et le TID), et enfin son propre TLS (Thread Local Storage).
    Tout le reste est commun à tous les threads du même processus, notamment le mapping mémoire, les handles sur ressources, le PID, etc.

    Citation Envoyé par ram-0000 Voir le message
    Non, dans le cas de plusieurs thread, il y a partage des sections de données, elles ne sont pas rechargées. C'est la grosse différence entre thread et processus.
    Attention quand même : une DLL déjà en mémoire et attachée au processus s'attache également au thread lors du lancement de ce dernier (cf. fonction "DllMain").
    La DLL n'est bien sûr pas rechargée, mais elle peut être initialisée plus ou moins automatiquement lors de la création d'un thread.

    C'est notamment pour cette raison que l'on conseille de créer tous les threads requis en début de programme, puis de les suspendre pour les faire bosser en fonction des besoins.

    De plus, à titre d'information générale : Windows est très efficace sur la gestion des threads, et bien moins sur la gestion des processus. C'est exactement l'inverse pour les systèmes Unix, notamment Linux.

    Citation Envoyé par klakman Voir le message
    Tu parles bien de sémaphores?
    Qui permet ( dîtes moi si je me trompe ) de bloquer tout autres threads nécessitant un accès à une zone mémoire, pendant qu'un thread exécute ses actions dessus.
    Sémaphores, mutex, barrières, etc. De manière générale, ce sont des "objets de synchronisation".

    Citation Envoyé par klakman Voir le message
    Peut-il y avoir des protections qui réservent un espace mémoire à un unique thread?
    De façon "inviolable", non. D'ailleurs, même une zone protégée par un mutex peut être accédée de façon sale (sans prendre le mutex, donc), et un thread peut donc y faire n'importe quoi. Les zones ne sont protégées que parce que le développeur le veut bien, et non pas parce que c'est impossible autrement.

    Les seules données strictement spécifiques à un thread, et inaccessibles aux autres threads, c'est le TLS.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 82
    Par défaut
    Merci pour ces précisions.

    Seulement ça fait un petit moment que je cherche des infos sur le TLS des threads et j'ai pas trouvé d'info sur le faite que c'était inaccessible par les autres threads.

    Voici ce que j'ai trouvé entre autre :

    The address of a thread variable may be freely used during the variable's lifetime by any thread in the program.
    ici : http://www.open-std.org/jtc1/sc22/wg...006/n1966.html

    et la documentation microsoft :

    With thread local storage (TLS), you can provide unique data for each thread that the process can access using a global index.
    ici : http://msdn.microsoft.com/en-us/libr...49(VS.85).aspx

    Je n'ai pas vu de mention spécifiant que les données spécifiées étaient inaccessible par un autre thread que l'utilisateur de cette donnée.

    Maintenant peut être que c'est implicite et que je n'ai pas très bien compris le TLS?

  8. #8
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Alors : le TLS, en très très très schématisé, c'est un tableau de pointeurs, dont la taille varie en fonction du système d'exploitation. Disons qu'il fait 64 entrées pour l'exemple.

    Lorsqu'un thread, n'importe lequel, alloue un TLS, il récupère un indice dans ce tableau. Par exemple, 12, car les 11 premiers étaient déjà alloués.

    Exactement au même moment, tous les threads du processus ont alors accès à leur propre TLS à l'indice 12. Le "12" est donc global au processus, il a été créé par un des threads du processus (le principal en général), et est lu par les autres (les threads secondaires). Bien entendu, comme ils ne font que lire, pas besoin de mutex.

    Cependant, chaque thread a sa PROPRE valeur à l'adresse 12 en question. Si le thread A y met par exemple "0xDEADBEEF" et le thread B "0xCAFEBABE", alors le thread A n'a absolument aucun moyen de connaître la valeur contenue dans le TLS de B, et réciproquement. Toutefois, les deux threads partagent bien entendu le même indice, qui correspond en général à une donnée particulière.

    A quoi servent les TLS, alors ? A rendre une fonction dans ton code totalement indépendante du thread qui l'exécute. Elle ira récupérer les données spécifiques du thread dans le TLS (à un indice particulier, global au processus donc), et grâce à cela, n'affectera QUE le thread courant. Si la fonction se fait interrompre par elle-même, au sein d'un autre thread, le TLS change et donc les données aussi, aucun conflit d'accès.

    Il faut et il suffit de mettre les bonnes données dans le TLS. Habituellement, on crée une structure (plus ou moins complexe), contenant tout ce dont le thread peut avoir besoin, et on passe cette structure au thread à sa création qui va alors immédiatement en stocker l'adresse dans son TLS. Ainsi, toute fonction dépendante du contexte (pour obtenir une socket, par exemple, ou un handle sur un fichier de log, ou n'importe quoi d'autre !) peut obtenir les données propres du thread sans requérir de passage de paramètres explicites. Ces paramètres font alors partie de l'environnement du thread.

    Pour la petite histoire, le système d'exploitation utilise par exemple le TLS pour stocker des données comme le "errno" (ou "GetLastError" sous Win32), de façon à ne pas polluer un thread donné avec les valeurs d'erreurs des autres threads.


    Est-ce plus clair ?
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 82
    Par défaut
    Merci bien bien plus clair! ( Y a pas à dire je comprends mieux en francais )

    Donc si j'ai bien compris, le TLS est un tableau qui stoque les infos particulière au thread en cours. Donc si on change de thread, le LPVOID de la case "12" ( pour reprendre ton exemple ) change pour pointer sur une nouvelle adresse?

    Si oui, justement l'adresse sur laquelle le LPVOID pointe, on est d'accord qu'il s'agit du première octet de la donné? Mais où cette donnée est stoquée?
    Elle peut être stoquée n'importe où ( ou presque ) dans la mémoire du processus? ( Au final comme une variable classique par exemple )

    Une autre petite question, de 0 à 11 quelles types d'informations on a? des choses comme priorité du thread, ...?

  10. #10
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par klakman Voir le message
    Donc si on change de thread, le LPVOID de la case "12" ( pour reprendre ton exemple ) change pour pointer sur une nouvelle adresse?
    C'est exactement ça.

    Citation Envoyé par klakman Voir le message
    Si oui, justement l'adresse sur laquelle le LPVOID pointe, on est d'accord qu'il s'agit du première octet de la donné?
    Ou l'adresse de la structure, suivant comment tu veux l'interpréter.

    Citation Envoyé par klakman Voir le message
    Mais où cette donnée est stoquée?
    Où tu veux, tant que tu peux en avoir l'adresse, on s'en fiche. Les autres threads n'y ont normalement pas accès, sauf à communiquer explicitement cette adresse à d'autres threads (ce que l'on ne fait bien sûr pas).
    Pour ma part, dans la fonction principale du thread, je recopie cette structure en tant que variable locale, puis j'initialise le TLS avec. Ainsi, tant que le thread est vivant, la donnée existe, et dès qu'on sort de la fonction (=fin du thread), elle disparait en même temps que le thread lui-même.

    Citation Envoyé par klakman Voir le message
    Une autre petite question, de 0 à 11 quelles types d'informations on a? des choses comme priorité du thread, ...?
    Tu n'as en fait pas à le savoir : ce sont d'autres routines qui les utilisent, pas les tiennes, c'est tout ce que tu as à savoir. Manipuler ces données sans savoir exactement ce qu'elles contiennent peut crasher au mieux ton thread, au pire ton système.
    Tu ne dois utiliser que tes slots de TLS, que tu as alloués toi-même. Et jamais les autres.

    Un autre exemple typique d'utilisation d'un TLS, c'est une DLL complexe qui se sert dudit TLS pour stocker les informations propres au thread, passés en général via une fonction de type "Register".
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 82
    Par défaut
    Merci pour tout, je pense avoir compris les bases du multi threading, et je vais pouvoir progresser seul avec un peu de code maintenant.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Question sur les threads
    Par Linio dans le forum Concurrence et multi-thread
    Réponses: 10
    Dernier message: 21/10/2005, 09h08
  2. Question sur les LinkedList et les threads
    Par berg dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 10/09/2005, 19h16
  3. Question sur les threads
    Par nicolas66 dans le forum MFC
    Réponses: 4
    Dernier message: 03/06/2005, 20h57
  4. Question simple sur les threads :)
    Par momox dans le forum C++Builder
    Réponses: 2
    Dernier message: 15/06/2003, 04h13
  5. question sur les variables globales et les thread posix
    Par souris_sonic dans le forum POSIX
    Réponses: 5
    Dernier message: 13/06/2003, 13h59

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