2009-08-03 8 views
18
#include <stdio.h> 

int main() { 
    while(!DONE) { 
    /* check for stuff */ 
    } 
    return 0; 
} 

L'exemple de code ci-dessus utilise 100% cpu jusqu'à ce que DONE soit vrai. Comment puis-je implémenter un programme qui boucle et ne se termine que lorsque fait, mais qui n'utilise pas 100% cpu? Les langages modernes utilisent quelque chose comme App.ProcessMessages ou quelque chose comme ça pour donner au système d'exploitation le contrôle pour le moment et revenir ensuite à la boucle.C Boucle principale sans unité centrale 100%

Je suis novice en la matière C, évidemment ... en utilisant le dernier GCC, Linux et Windows (une solution portable serait super!)

+8

Vous devez utiliser un objet de synchronisation, un que vous pouvez attendre jusqu'à ce qu'il soit signalé, de cette façon vous ne consommera pas du tout CPU. –

+2

Qu'est-ce que 'DONE' et qu'est-ce qui le rendra différent de zéro? Vraisemblablement, il est logique de continuer le traitement jusqu'à ce que le 'vérifier les choses' évalue quelque chose qui définit DONE comme étant non nul? –

+0

Lasse V. Karlsen: Votre solution semble avoir du sens (elle a probablement beaucoup de sens, mais je n'ai pas cette connaissance). Pourriez-vous élaborer? Dois-je enquêter sur les discussions? (Un exemple serait bien) Charles Bailey: DONE devrait être un int (fait au lieu de DONE) et il serait mis à 1 lorsque l'utilisateur a choisi de quitter l'application, par exemple. Je suis désolé si je ne peux pas m'expliquer assez bien .. – pwseo

Répondre

16

Cela dépend de ce que vous voulez faire dans cette boucle.

Si vous attendez à l'intérieur de la boucle (c.-à-d. Si vous enfoncez une touche), votre mécanisme gaspillera les ressources du système et ne donnera rien en retour. il suffit de dormir, mais de préférence, un événement qui déclenche la réalisation de quelque chose de significatif.Par exemple, une opération de fichier (stdin est aussi un fichier) serait un mécanisme portable, qui cédera la place à d'autres applications jusqu'à ce que des données soient disponibles. plus spécifique, il peut être nécessaire de plonger dans des sémaphores ou des signaux qui sont souvent dépendants du système d'exploitation.Une couche d'abstraction peut résoudre ce problème

Si vous faites quelque chose d'utile (c'est-à-dire de traiter beaucoup de données), alors 100% CPU seulement signifie que le processeur est nous ed de la manière la plus efficace. Vous pouvez compter sur le système d'exploitation pour céder la place à d'autres tâches prioritaires. L'utilisation d'une fonction comme le sommeil réduira l'utilisation du processeur, mais votre application sera plus lente. Il faudra pour obtenir un compromis entre la performance acceptable et la charge du processeur. La vitesse d'exécution maximale sera définie par votre paramètre de veille, et non plus par la vitesse du processeur. En outre, si la puissance est une préoccupation (c'est-à-dire la durée de vie de la batterie), alors cela nécessitera que le CPU se réveille (fin de la période de sommeil) sans travail à effectuer; c'est-à-dire un gaspillage différent des ressources du système.

+0

Je suppose que je vais devoir apprendre les sémaphores et les signaux puis Des pointeurs spécifiques sur cela? :) – pwseo

+2

Quel genre de traitement est à l'intérieur de la boucle principale? Les messages, signaux, sémaphores sont plus liés au système d'exploitation que le langage sous-jacent. Par exemple, http://www.ibm.com/developerworks/eserver/library/es-win32linux-sem.html montre comment les sémaphores sont gérés dans Windows par rapport à Linux. Si vous avez besoin de prendre en charge les deux, vous pouvez soit utiliser POSIX (facultatif pour Windows, c'est-à-dire dans cygwin), soit placer le code dans un module dépendant de la plateforme que vous créez pour chaque système d'exploitation. – Adriaan

1

utilisation

sommeil (int Millisecondes)

+3

L'argument pour dormir est en fait un nombre de secondes, pas millisecondes. –

+1

Je pense que cela dépend de l'OS ... alors que vous avez raison sur le fait que le paramètre est secondes sous Unix/Linux/* BSD, je pense que je me souviens qu'il est en millisecondes sous Windows ... Cela fait des années que je puisse avoir tort ... – Nicolas

+5

sleep() nécessite le nombre de secondes. usleep() (BSD et POSIX) prend des microsecondes. nanosleep() (POSIX aussi) prend des nanosecondes. – qrdl

3

Qu'est-ce que exactement vérifiez-vous?

Si vous vérifiez quelque chose de volatile qui est modifié par le matériel ou un autre processus, appelez sleep dans votre boucle.

Si vous attendez un descripteur de fichier ou un descripteur de socket réseau, vous devrez utiliser select ou poll dans votre boucle pour attendre que le descripteur prenne des données prêtes à être consommées.

0

Utilisez yield().

+0

Ceci n'est pas portable, car il n'est défini ni par le standard C ni par POSIX. –

+1

Cela ne donnerait-il pas plus de temps aux autres processus, tout en prenant tout le temps que les autres processus ne consomment pas? – liori

0

Si je devine correctement (je ne sais pas à ce sujet), l'équivalent de App.ProcessMessages fait blocage IO. Et comme je ne connais aucune implémentation de C sur un système d'exploitation multitâche qui utilise l'interrogation, tout C IO standard devrait être sûr.

5

Vos deux options seraient l'interrogation et une sorte de notification d'événement.

L'interrogation serait plus facile à programmer - en gros, vous avez votre thread en veille pendant un court instant à chaque passage dans la boucle. Cela libère le processeur à d'autres tâches. L'inconvénient est qu'il y aura un retard dans votre code "vérifier les choses" - donc si vous dormez pendant une seconde, cela peut prendre jusqu'à une seconde avant que votre code ne détecte la condition. Votre code ici sera facile à mettre en communication.

L'autre option consiste à attendre un événement POSIX conditionnel ou Windows ou quelque chose comme ça. Non seulement ce code sera changé, mais le «truc que vous vérifiez» devra déclencher le drapeau pour dire que c'est fait. Ce serait un code un peu moins portable, bien qu'il y ait probablement des bibliothèques pour faire abstraction de la plate-forme. Mais vous obtiendrez des résultats immédiats à l'événement, et aucun temps perdu du processeur à la recherche de choses qui ne sont pas là.

+1

+1 pour suggérer l'utilisation de la synchronisation POSIX. –

9

Vous avez plusieurs choix:

  1. Utilisez sleep() pour forcer le processus de suspension périodiquement et permettre à d'autres processus d'utiliser le CPU
  2. Exécuter à un niveau de priorité inférieur - ce qui entraînera le système d'exploitation à affecter moins de temps processeur
  3. Utilisez un mutex ou un autre objet de synchronisation pour détecter le moment où le travail est disponible - ce qui évitera au processeur de consommer du temps processeur à moins qu'il ne travaille réellement
  4. Si vous travaillez plus vite que vous ne pouvez le traiter - Vous devrez peut-être encore Soit une sorte de modèle de sommeil/priorité pour éviter de consommer complètement le CPU.

L'option # 2 peut être difficile à faire d'une manière neutre pour la plate-forme/le système d'exploitation. Votre meilleur pari est de lancer le processus et de changer sa priorité dans l'environnement d'exécution.

0

Sous Windows, vous pouvez utiliser Sleep (int millisecondes), défini sous windows.h.

2

Si j'ai bien compris, vous avez dit dans les commentaires que DONE peut être modifié à partir d'autres threads. Si c'est le cas, les variables de condition ont un sens. Avec pthreads, on le ferait:

dans le thread qui attend:

pthread_mutex_lock(&mutex); 
while (!DONE) { 
    pthread_cond_wait(&cond, &mutex); 
} 
pthread_mutex_unlock(&mutex); 

Dans d'autres threads, lorsque vous avez terminé est changé:

pthread_mutex_lock(&mutex); 
DONE = 1; 
pthread_cond_signal(&cond); 
pthread_mutex_unlock(&mutex); 
+0

Vous pouvez déverrouiller un fil d'un autre fil? – user457015

Questions connexes