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 :

Boucle principale d'un programme


Sujet :

C

  1. #1
    Membre régulier
    Inscrit en
    Avril 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 33

    Informations forums :
    Inscription : Avril 2010
    Messages : 66
    Points : 70
    Points
    70
    Par défaut Boucle principale d'un programme
    Bonjour,

    Voilà ça fait déjà pas mal de temps que je me pose la question et je ne sais pas comment "googliser" ce genre de question.
    Je me demande, autant au niveau du code qu'au niveau physique, comment certains programmes peuvent s'exécuter et "attendre" des instructions sans tout à fait les attendre et sans utiliser 100% du CPU ?
    Quand on lance un programme graphique, prenons par exemple, la calculatrice de Windows, le programme se lance et attends qu'on agisse sur l'interface. Mais au niveau du code, pour "attendre", il faut faire une boucle, or si on fait une boucle qui "checkerait" de nouvelles informations (appui d'une touche par exemple), tant qu'on ne quitterait pas, la boucle serait infinie et donc on utiliserait 100% du CPU.
    Au niveau physique, le processeur lit/exécute un fichier binaire instruction par instruction, comment peut-on dire au processeur d'attendre (donc sans utiliser de ressources du CPU) tout en lui disant "Fais attention, si l'utilisateur agit sur quelque chose, tu dois réagir" ?
    Ce n'est pas évident d'être très clair et j'essayerai de nouveau d'imager ma question si je n'ai pas été compris.
    En gros, c'est un peu : Comment fonctionne la boucle ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    MSG msg;
    while(GetMessage(&msg,NULL,0,0))
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    ... de l'Api Win32 sans que l'on tombe dans une boucle infinie à attendre l'interaction de l'utilisateur ou un quelconque autre évenement.
    Ou encore sous Qt, comment son checker en permanence les QObject::connect() ?

    Si vous connaissez ne serait-ce qu'un mot clé ou des liens sur cela, je suis preneur. Merci d'avance.

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 400
    Points : 23 776
    Points
    23 776
    Par défaut
    Bonjour,

    En fait, la réponse se trouve au niveau de ton point de vue de la conception du système. Le micro-processeur, en fait, ne s'arrête jamais de travailler. Il tourne toujours en boucle (à certaines exceptions près comme HLT, et le fait qu'il puisse éventuellement descendre en fréquence). C'est donc ton système d'exploitation qui décide si le temps passé est consacré à quelque chose d'utile ou à ne rien faire. La clé du problème se trouve donc dans l'interaction de ton processus avec le système.

    De là, deux solutions : soit l'interface graphique, la queue de messages, etc. font directement partie du système (pas forcément génial) et, dans ce cas, le fait même d'appeler une fonction système attendant le prochain message indique au système que tu es actuellement inactif et ton processus peut-être classé comme tel. Si ce n'est pas le cas, alors il faut construire toute ton interface au-dessus d'appels système qui, eux, peuvent être bloquants.

    Dans ton exemple, c'est GetMessage() qui est bloquante. L'appel se fait bien, mais la fonction ne ressortira pas tant qu'un message ne sera pas arrivé. Ensuite, il sera retourné naturellement à l'appelant (ici, ton while) sans que ton programme ne s'aperçoive de quoi que ce soit.

    Sous UNIX, par exemple, la communication inter-processus se fait préférentiellement via les « tubes » (pipes) qui sont en fait un canal de communication géré comme un fichier, unidirectionnel, avec un processus écrivain d'un côté et un lecteur de l'autre. Ces pipes sont ce qui se fait de plus simples en la matière, mais on peut tout construire au-dessus. Comme ils sont gérés par le système, le fait même de lire un caractère sur un tube vide avec fgetc(), par exemple, provoque la mise en attente du processus. C'est ce qui se passe quand tu lis l'entrée standard (stdin) par défaut, et que tu attends que quelqu'un tape une touche.

    De là, tu peux très bien définir un de ces tubes comme étant la source de tes messages.

    Tu peux également, ensuite, remplacer les tubes par des sockets qui se gèrent quasiment de la même façon une fois qu'ils sont ouverts. Ensuite, tu écris une bibliothèque qui fait tout ce travail à ta place et qui l'enrobe dans des jolis noms de fonctions. C'est ce que fait X-Window (toujours sous Unix), par exemple. Et cela te permet d'exécuter un processus sur une machine et de déporter l'affichage sur une autre, sans que l'architecture globale n'ait besoin d'avoir été explictement conçue pour, à la base.

  3. #3
    Membre régulier
    Inscrit en
    Avril 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 33

    Informations forums :
    Inscription : Avril 2010
    Messages : 66
    Points : 70
    Points
    70
    Par défaut
    Donc si j'ai bien compris, l'OS s'occupe, suite à l'appel d'une fonction système, de "placer" un processus en "inactif" et lorsque l'utilisateur interagit avec le processus, un message est envoyé (à l'OS ?) vers le processus qui récupère ce message grâce à GetMessage() et qui peut ensuite le traiter ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    De là, tu peux très bien définir un de ces tubes comme étant la source de tes messages.
    Donc d'après ce que tu me dis, il est possible, sous Unix, de rediriger les messages vers un file descriptor et à partir du processus, le lire avec un read(), le read() étant alors la fonction bloquante ?

    En tout cas merci pour toutes ces informations, je pense que je vais continuer mes recherches vers ces fameuses 'fonctions bloquantes', voir ce qui se cache derrière read() et derrière GetMessage().
    Encore merci et bonne soirée

    Edit : Pour d'autres personnes que cela intéresserait, je viens de trouver un article sur Wikipédia : http://en.wikipedia.org/wiki/Event_loop (en anglais) qui semble donner de nombreuses informations à ce sujet.

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 400
    Points : 23 776
    Points
    23 776
    Par défaut
    Citation Envoyé par Hoder Voir le message
    Donc si j'ai bien compris, l'OS s'occupe, suite à l'appel d'une fonction système, de "placer" un processus en "inactif" et lorsque l'utilisateur interagit avec le processus, un message est envoyé (à l'OS ?) vers le processus qui récupère ce message grâce à GetMessage() et qui peut ensuite le traiter ?
    Presque. Les messages arrivent dans une file d'attente et GetMessage() récupère le premier. Si la file est vide, GetMessage() va rester en attente jusqu'à ce qu'il y en ait un qui pointe le bout de son nez. La manière dont les messages sont effectivement véhiculés ne concerne que la bibliothèque, et est transparente pour le programmeur.

    L'idée est qu'il y a déjà des systèmes de communications inter-processus fournis par le système qui fonctionnent de la même façon. Donc autant les utiliser. Sinon, il faut utiliser d'autres artifices, comme les sémaphores. Mais dans tous les cas, tu finis toujours par demander au système de te mettre en attente, d'une manière ou d'une autre.

    Donc d'après ce que tu me dis, il est possible, sous Unix, de rediriger les messages vers un file descriptor et à partir du processus, le lire avec un read(), le read() étant alors la fonction bloquante ?
    Tout-à-fait.

  5. #5
    Membre régulier
    Inscrit en
    Avril 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 33

    Informations forums :
    Inscription : Avril 2010
    Messages : 66
    Points : 70
    Points
    70
    Par défaut
    Merci pour toutes ces informations, j'y vois désormais bien plus clair =) Ca me tracassait de pas savoir comment cela fonctionnait.

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

Discussions similaires

  1. Créer une boucle qui relance le programme
    Par vally74 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 17/05/2008, 20h56
  2. Réponses: 19
    Dernier message: 16/03/2008, 23h45
  3. Réponses: 8
    Dernier message: 12/06/2007, 16h10
  4. Boucle répétitive pour mon programme
    Par jena dans le forum MATLAB
    Réponses: 2
    Dernier message: 19/05/2007, 12h41
  5. Réponses: 7
    Dernier message: 08/01/2007, 12h11

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