Suggestions d'utilisation des systèmes d'exécution et des priorités

Aide LabVIEW 2014

Date d'édition : June 2014

Numéro de référence : 371361L-0114

»Afficher les infos sur le produit
Télécharger l'aide (Windows uniquement)

Dans la plupart des applications, il n'est pas nécessaire d'utiliser les niveaux de priorité ou un système d'exécution différent du système d'exécution standard, lequel gère automatique le multitâche des VIs. Par défaut, tous les VIs s'exécutent dans le système d'exécution standard avec la priorité normale. Dans une application multithread, un thread distinct gère l'activité de l'interface utilisateur, de sorte que les VIs sont isolés de l'interaction de l'interface utilisateur. Dans une application monothread, le système d'exécution alterne entre l'interaction de l'interface utilisateur et l'exécution des VIs, ce qui donne des résultats semblables.

En général, la meilleure façon d'octroyer une priorité d'exécution consiste à utiliser des fonctions Attendre pour ralentir les boucles à priorité plus faibles de l'application. Ceci est particulièrement utile dans le cas des boucles des VIs de l'interface utilisateur car des délais de 100 à 200 ms se remarquent à peine.

Si vous utilisez des priorités, faites-le prudemment. Si vous développez des VIs à priorité plus élevée qui s'exécutent pendant un certain temps, vous pouvez ajouter des attentes aux VIs qui se trouvent dans des sections moins critiques de code pour qu'ils partagent le temps avec les tâches à priorité plus faible.

Soyez prudent lorsque vous manipulez des variables globales, des variables locales et d'autres ressources externes que d'autres tâches modifient. Utilisez une technique de synchronisation telle qu'une variable globale fonctionnelle ou un sémaphore pour protéger l'accès à ces ressources.

Synchronisation de l'accès aux variables globales et locales, et aux ressources externes

Comme le système d'exécution peut exécuter plusieurs tâches en parallèle, vous devez vous assurer que l'accès aux variables globales et locales ainsi qu'aux ressources suit un ordre approprié.

Pour éviter les situations de compétition

Il y a plusieurs façons d'éviter les situations de compétition. Le plus simple est de faire en sorte qu'une variable globale ne puisse être changée qu'en un seul endroit de l'application.

Dans une application monothread, vous pouvez utiliser un VI ayant la priorité sous-programme pour lire ou écrire une variable globale sans déclencher une situation de compétition car ce type de VI ne partage pas le thread d'exécution avec d'autres VIs. Dans une application multithread, le niveau de priorité sous-programme ne garantit pas un accès exclusif à une variable globale car un autre VI s'exécutant dans un thread différent peut accéder à cette variable en même temps.

Variables globales fonctionnelles

Les variables globales fonctionnelles sont des VIs non réentrants qui utilisent des boucles comportant des registres à décalage non initialisés pour stocker des données globales. En général, une variable globale fonctionnelle a un paramètre d'entrée action qui spécifie la tâche effectuée par le VI. Vous pouvez utiliser des variables globales fonctionnelles afin de protéger des sections de code critiques qui effectuent une action sur une variable, et éviter ainsi les situations de compétition associées aux variables globales. Si deux sections de code parallèles lisent la valeur de la même variable globale, la modifient, puis la réécrivent en même temps, des situations de compétition risquent de se produire car une des sections risque d'écraser les modifications apportées par l'autre. Utilisez des variables globales fonctionnelles pour protéger les actions qui modifient des données. Par exemple, les variables globales fonctionnelles permettent d'éviter les situations de compétition des sections critiques qui lisent, incrémentent et écrivent des données en mémoire, ou qui mettent à jour une base de données ou modifient un fichier.

L'illustration suivante représente une variable globale fonctionnelle qui met en œuvre une variable globale de comptage simple. Le VI utilise un registre à décalage non initialisé dans une boucle While pour stocker le résultat de l'opération. Les actions de cet exemple sont initialiser, lire, incrémenter et décrémenter.

À chaque fois que vous appelez le VI, le diagramme dans la boucle s'exécute une seule fois. Selon le paramètre action, la condition à l'intérieur de la boucle s'initialise, ne change pas, ou augmente ou diminue par incrément la valeur du registre à décalage.

Bien que les variables globales fonctionnelles peuvent servir à implémenter des variables globales simples, comme le montre l'exemple précédent, elles sont particulièrement utiles pour implémenter des structures de données plus complexes, comme une pile ou un buffer de file d'attente. Vous pouvez aussi utiliser des variables globales fonctionnelles pour donner accès aux ressources globales, comme les fichiers, les instruments et les périphériques d'acquisition de données, qu'il n'est pas possible de représenter par une variable globale, puisque les appels de la variable globale fonctionnelle s'exécutent en séquence si vous ne définissez pas que le VI est réentrant.

Les variables globales fonctionnelles permettent de résoudre la plupart de problèmes de synchronisation, car le VI global fonctionnel assure qu'à un moment donné un seul appelant peut changer les données qu'il contient. Les variables globales fonctionnelles ont un inconvénient : si vous voulez changer la façon dont vous modifiez la ressource qu'elles renferment, vous devez changer le diagramme du VI global fonctionnel et ajouter une nouvelle action. Dans les applications où l'utilisation des ressources globales change souvent, ces changements peuvent être gênants. Dans ces cas-là, développez l'application pour pouvoir utiliser un sémaphore pour protéger l'accès à la ressource globale.

Page d'accueil sur les Méthodes de communication de données

Sémaphores

Un sémaphore, appelé aussi mutex, est un objet qui peut être utilisé pour protéger l'accès aux ressources partagées. Le code qui permet d'accéder à la ressource partagée est appelé section critique. Un sémaphore protège l'accès à une section critique en autorisant seulement un nombre limité de tâches à obtenir simultanément l'accès au sémaphore. En général, il est souhaitable qu'à un moment donnée, une seule tâche puisse accéder à une section critique protégée par un sémaphore commun. Il est possible toutefois de configurer un sémaphore pour permettre à plusieurs tâches (jusqu'à une limite prédéfinie) d'accéder à une section critique.

Les cas les plus fréquents d'utilisation de sémaphores nécessitent les étapes suivantes :

  1. Identifier les sections de code critiques — Vous utilisez généralement des sémaphores pour contrôler l'accès aux sections de code qui permettent d'accéder à une ressource partagée. Par exemple, si plusieurs sous-VIs interagissent avec la même variable globale, il est conseillé de faire en sorte que ces sections de code ne s'exécutent pas simultanément afin d'éviter une situation de compétition. Dans cet exemple, chaque section de code qui lit ou écrit dans la variable globale est une section de code critique. Les E/S sur fichiers et de périphériques sont d'autres exemples courants de code qui constitue une section critique.
  2. Créer un sémaphore que les sections critiques partageront — Utilisez le VI Obtenir une référence de sémaphore pour créer un nouveau sémaphore ou pour obtenir un sémaphore pré-existant en fonction de son nom. Par défaut, un nouveau sémaphore ne peut être acquis que par une tâche à la fois. Pour autoriser plusieurs tâches à accéder simultanément au sémaphore, spécifiez le nombre désiré de tâches pour l'entrée taille du VI Obtenir une référence de sémaphore.
  3. Acquérir l'accès au sémaphore avant chaque section critique — Utilisez le VI Acquérir un sémaphore pour demander l'accès au sémaphore. Si le sémaphore est utilisé par une autre tâche, le flux de données s'arrête au VI Sémaphore jusqu'à ce que l'autre tâche libère le sémaphore. Une fois qu'une section de code a acquis un sémaphore, aucune autre tâche ne peut l'acquérir jusqu'à ce que le code le libère. Par conséquent, le code compris entre le VI Acquérir un sémaphore et le VI Libérer un sémaphore est assuré de terminer son exécution avant qu'une autre section de code protégée ne commence la sienne.
  4. Libérer l'accès au sémaphore après chaque section critique — Utilisez le VI Libérer un sémaphore pour libérer l'accès au sémaphore de sorte qu'une autre tâche qui attend ce sémaphore puisse l'acquérir et exécuter sa propre section de code critique.
  5. Libérer la référence au sémaphore — Utilisez le VI Libérer une référence de sémaphore pour libérer cette référence. Pour assurer une utilisation efficace des ressources système, n'oubliez pas de libérer la référence de sémaphore dès que vous pouvez confirmer que toutes les tâches ont fini d'utiliser ce sémaphore.
Remarque  Certaines utilisations avancées de sémaphores acquièrent et libèrent le sémaphore dans des sections de code différentes.

Reportez-vous au VI Simple Semaphore.vi dans le répertoire labview\examples\Synchronization\Semaphore pour consulter un exemple d'utilisation du VI Obtenir une référence de sémaphore et du VI Libérer une référence de sémaphore.

L'illustration suivante montre comment utiliser un sémaphore pour protéger les sections critiques. Un autre VI a créé le sémaphore et a fait passer la référence à ces sous-VIs. Comme ce sémaphore a une taille de 1, seule une tâche à la fois peut accéder au sémaphore.

Chacun des diagrammes précédents contient une section de code critique qui accède à la même variable globale, Compte. Par conséquent, ces diagrammes partagent le même sémaphore. Avant qu'un des diagrammes exécute sa section critique, il appelle le VI Acquérir un sémaphore pour détecter si l'autre diagramme a déjà acquis le sémaphore. Si le sémaphore est occupé, le VI Acquérir un sémaphore attend qu'il devienne disponible. Dès que le sémaphore est disponible, le VI Acquérir un sémaphore renvoie FAUX pour hors délai, indiquant ainsi que le diagramme a la permission d'exécuter sa section critique. Lorsque le diagramme a terminé d'exécuter sa section critique, le VI Libérer un sémaphore libère le sémaphore, ce qui permet à un autre diagramme en attente de reprendre l'exécution.

Durée d'un sémaphore

Un sémaphore reste en mémoire tant qu'un VI de niveau principal qui n'est pas inactif possède une référence à ce sémaphore. Si le VI de niveau principal devient inactif, LabVIEW libère toutes les références de sémaphore appartenant au VI, y compris les références qui se trouvent dans les sous-VIs du VI de niveau principal. Si LabVIEW libère la dernière référence à un sémaphore nommé, LabVIEW détruit le sémaphore. Comme vous ne pouvez obtenir qu'une seule référence à un sémaphore sans nom, LabVIEW supprime un sémaphore sans nom si le VI de niveau principal devient inactif. Pour utiliser un sémaphore sur plusieurs VIs de niveau principal, nommez le sémaphore et appelez le VI Obtenir une référence de sémaphore à partir de chaque VI de niveau principal de sorte qu'ils obtiennent chacun leur propre référence au sémaphore.

CET ARTICLE VOUS A-T-IL ÉTÉ UTILE ?

Pas utile