Pour la communication entre tâches ou pour partager des données entre deux tâches de RTOS, nous utilisons des files d'attente. Mais le problème avec les files d'attente est qu'elles sont lentes .... Elles copient les données dans le tampon, puis la gestion Mutex et ensuite le transfert de données. C'est énormément lent si vous devez transférer des données volumineuses. Un autre problème est si la même file d'attente est accessible par plusieurs tâches. L'image devient alors la suivante: - Attendez d'abord pour accéder à la file d'attente puis à la gestion interne des mutex de la file d'attente, puis au transfert de données.
Cela augmente les frais généraux sur le système. Quel pourrait être le remplacement efficace des files d'attente?
(Je suppose que cette question est indépendante du RTOS que nous utilisons. La plupart des RTOS gèrent les files d'attente de cette manière uniquement)
Réponses:
Les files d'attente fonctionnent de cette façon car il s'agit d'un modèle de transaction thread-safe pour la communication entre les tâches. Vous risquez des problèmes de corruption et / ou de propriété des données dans tout schéma moins strict.
Copiez-vous les données dans un tampon en mémoire puis passez-vous un pointeur avec les éléments de file d'attente, ou essayez-vous de passer toutes les données dans les éléments de file d'attente eux-mêmes? Si vous ne passez pas de pointeurs, vous obtiendrez une augmentation des performances en faisant cela au lieu de passer un octet à la fois dans les éléments de file d'attente.
la source
Un moyen simple consiste à placer un pointeur sur les données dans la file d'attente et à consommer les données à l'aide du pointeur.
Notez que vous échangez la sécurité contre des performances de cette façon car vous devez vous assurer que:
Si vous n'utilisez pas de mémoire allouée dynamiquement, vous n'avez pas à la désallouer, mais vous devez toujours vous assurer que la zone de mémoire n'est pas réutilisée avant que les données aient été consommées.
la source
Des files d'attente sans verrouillage peuvent être implémentées pour le cas d'un seul producteur / consommateur unique, et vous pouvez souvent concevoir votre logiciel pour minimiser le nombre de files d'attente multi-producteurs ou multi-consommateurs.
Une file d'attente sans verrou peut être construite comme suit: Allouez un tableau des éléments à communiquer, ainsi que deux entiers, appelez-les Head et Tail. Head est un index dans le tableau, où l'élément suivant sera ajouté. Tail est un index dans le tableau, où l'élément suivant est disponible pour être supprimé. La tâche de producteur lit H et T pour déterminer s'il y a de la place pour ajouter un élément; écrit l'élément dans l'index H, puis met à jour H. Les tâches de consommation lisent H et T pour déterminer s'il y a des données disponibles, lit les données de l'index T, puis met à jour T. Fondamentalement, il s'agit d'un tampon en anneau auquel accèdent deux tâches, et le l'ordre des opérations (insérer, puis mettre à jour H; supprimer, puis mettre à jour T) garantit que la corruption des données ne se produit pas.
Si vous avez une situation avec plusieurs producteurs et un seul consommateur, ou un seul producteur et plusieurs consommateurs, vous avez effectivement une limitation de ressources quelconque, et il n'y a rien d'autre à faire que d'utiliser la synchronisation, car le limiteur de performances est plus susceptible de être le seul producteur / consommateur qu'un système d'exploitation avec le mécanisme de verrouillage.
Mais si vous avez plusieurs producteurs ET consommateurs, cela vaut la peine de passer du temps (dans l'espace de conception) pour voir si vous ne pouvez pas obtenir un mécanisme de communication plus coordonné; dans un cas comme celui-ci, la sérialisation de tout via une seule file d'attente fait définitivement de l'efficacité de la file d'attente le déterminant central des performances.
la source
On peut obtenir un fonctionnement efficace dans une file d'attente mono-consommateur multi-producteur sans verrouillage si la file d'attente elle-même contient des éléments suffisamment petits pour fonctionner avec une primitive de magasin de charge, de comparaison-échange ou similaire, et on peut utiliser un valeur réservée ou valeurs réservées pour des emplacements de file d'attente vides. Lors de l'écriture dans la file d'attente, le rédacteur effectue un échange de comparaison pour essayer de stocker ses données dans le prochain emplacement vide; si cela échoue, le rédacteur essaie l'emplacement suivant. Bien que la file d'attente conserve un pointeur vers le prochain emplacement vide, la valeur du pointeur est "consultative". Notez que si un système utilise compare-exchange plutôt que load-store-exclusive, il peut être nécessaire d'avoir une «famille» de différentes valeurs de «slot vide». Sinon, si entre le moment où le rédacteur trouve un emplacement de file d'attente vide et tente d'y écrire, un autre écrivain écrit la fente et le lecteur la lit, le premier écrivain mettrait sans le savoir ses données dans un endroit où le lecteur ne les verrait pas. Ce problème ne se produit pas dans les systèmes qui utilisent load-store-exclusive, car le magasin-exclusif détecterait que les données ont été écrites même si elles ont été réécrites à l'ancienne valeur.
la source
Vous pouvez accéder aux files d'attente plus efficacement en écrivant au-dessus de la file d'attente Normalement, la plupart des RTOS fournissent le support de l'ajout au début de la file d'attente, ce qui ne nécessite pas l'acquisition de mutex. Mais assurez-vous d'utiliser l'ajout au début de la file d'attente aussi peu que possible là où vous souhaitez simplement exécuter les données plus rapidement. Normalement, les structures de file d'attente ont une taille maximale, de sorte que vous ne pouvez pas mettre toutes les données dans la file d'attente, il est donc toujours facile de passer le pointeur.
à votre santé!!
la source
Les files d'attente ne sont pas intrinsèquement lentes. Leur mise en œuvre peut être.
Si vous copiez aveuglément des données et utilisez une file d'attente synchrone, vous verrez un impact sur les performances.
Comme d'autres affiches l'ont indiqué, il existe des alternatives sans verrou. Le cas d'un seul producteur / seul consommateur est simple; pour plusieurs producteurs et consommateurs, l' algorithme de file d'attente sans verrou de Michael et Scott (ce sont leurs noms de famille) est la norme et est utilisé comme base pour ConcurrentLinkedQueue de Java .
Il est possible d'optimiser le besoin de files d'attente dans certains cas, mais ils offrent des garanties de concurrence qui offrent généralement d'énormes avantages de simplification aux systèmes en vous permettant de découpler les tâches.
la source