Tâche: Décrire l'architecture d'exécution |
|
 |
Cette tâche définit une architecture de processus pour le système, reposant sur les classes actives, les instances de ces classes, ainsi que la relation entre ces classes et les processus et unités d'exécution de système d'exploitation. |
Disciplines: Analyse et conception |
|
Objet
-
Analyser les exigences liées aux accès concurrents
-
Identifier les processus et leurs cycles de vie
-
Identifier les mécanismes de communication interprocessus et attribuer les ressources de coordination entre
processus
-
Répartir les éléments de modèle entre les processus
|
Relations
Rôles | Exécutant principal:
| Exécutant supplémentaires:
|
Entrées | Obligatoire:
| Facultatif:
|
Sorties |
|
Utilisation des processus |
|
Description principale
Les objets actifs (c'est-à-dire les instances de classes actives) permettent de représenter les unités d'exécution
concurrentes dans le système : d'un point de vue théorique, chaque objet actif possède son propre fil de contrôle, et
d'un point de vue conventionnel, chaque objet est la racine d'un cadre de pile d'exécution. Le mappage des objets
actifs aux unités d'exécution ou processus de système d'exploitation effectifs peut varier selon les exigences de
réactivité, et sera influencé par la surcharge due aux changements de contexte. Par exemple, un certain nombre d'objets
actifs peuvent, grâce à un simple ordonnanceur, partager une seule unité d'exécution de système d'exploitation, donnant
ainsi l'illusion d'être exécutés simultanément. Cependant, si l'un des objets actifs adopte un comportement de blocage,
en exécutant par exemple des entrées-sorties synchrones, les autres objets actifs du groupe ne pourront pas répondre
aux événements produits lors du blocage de l'unité d'exécution de système d'exploitation.
A l'inverse, donner à chaque objet actif sa propre unité d'exécution de système d'exploitation devrait déboucher sur
une plus grande réactivité, tant que les ressources de traitement ne subissent pas d'impact négatif en raison de la
charge supplémentaire due aux changements de contexte.
Dans les systèmes en temps réel, les Produits :
Capsules sont recommandées pour la modélisation des accès concurrents. Comme les classes actives, chaque capsule
possède son propre fil de contrôle théorique, mais les capsules ont des sémantiques composites et une encapsulation
supplémentaire pour rendre plus malléable la modélisation de problèmes complexes en temps réel.
Cette tâche définit une architecture de processus pour le système, reposant sur les classes actives, les instances de
ces classes, ainsi que la relation entre ces classes et les processus et unités d'exécution de système
d'exploitation. De la même manière, pour les systèmes en temps réel, la définition de l'architecture de processus
reposera sur les capsules et leur mappage relatif aux processus et unités d'exécution de système d'exploitation.
Au début de la phase d'élaboration, cette architecture sera peu développée mais, à la fin de de l'élaboration, les
unités d'exécution et processus devront être bien définis. Les résultats de cette tâche sont enregistrés dans le modèle
de conception, et plus particulièrement dans la vue de processus (voir Concept : Vue de
processus).
|
Etapes
Analyse des exigences liées aux accès concurrents
Objet
|
Définir le degré d'exécution parallèle requis pour le système. Cette définition aidera à façonner
l'architecture.
|
Au cours de la Tâche : Identification des éléments de conception, nous avons abordé
les exigences liées aux accès concurrents qui sont engendrées essentiellement par des demandes naturelles d'accès
concurrents dans le domaine considéré.
Cette analyse a débouché sur la définition d'un ensemble de classes actives qui représentaient les fils de contrôle
logiques du système. Dans les systèmes en temps réel, ces classes actives sont représentées par le Produit : Capsule.
Au cours de cette étape, nous abordons d'autres sources d'exigences concernant les accès concurrents : les exigences
non fonctionnelles du système.
Les exigences liées aux accès concurrents dérivent des éléments suivants :
-
La mesure dans laquelle le système doit être distribué. Un système dont le comportement doit être distribué
sur des processeurs ou des noeuds nécessite presque une architecture multiprocessus. Un système qui utilise un
gestionnaire de transactions ou un système de gestion de base de données doit aussi tenir compte des processus
induits par ces sous-systèmes importants.
-
L'intensité de calcul des algorithmes clé. Afin d'obtenir des temps de réponse convenables, vous pouvez être
amené à placer les activités qui exigent un calcul intensif dans un processus ou une unité d'exécution à part, de
sorte que le système puisse encore répondre aux entrées de l'utilisateur au cours du calcul, même avec de moindres
ressources.
-
Le degré d'exécution parallèle pris en charge par l'environnement. Si le système d'exploitation ou
l'environnement ne prennent pas en charge des unités d'exécution (processus légers), il est inutile de prendre en
compte leur impact sur l'architecture du système.
-
La nécessité d'une tolérance aux pannes dans le système. Les processeurs de secours requièrent un processus
de secours, et nécessitent le maintien de la synchronisation entre les processus primaires et de secours.
-
Le pattern d'arrivée des événements dans le système. Dans les systèmes comportant des unités ou capteurs
externes, les patterns d'arrivée des événements entrants peuvent varier selon les capteurs. Certains événements
peuvent être périodiques (ils se produisent à intervalles réguliers, avec une petite marge de tolérance), d'autres
apériodiques (ils se produisent à intervalles irréguliers). En principe, les classes actives qui représentent des
unités générant différents patterns d'événements seront attribuées à différentes unités d'exécution de système
d'exploitation, avec différents algorithmes d'ordonnancement, afin de garantir le respect des échéances des
événements ou des traitements (si le système l'exige). Le même raisonnement s'applique aux capsules, lorsqu'elles
sont utilisées dans la conception de systèmes en temps réel.
Comme dans de nombreux problèmes architecturaux, ces exigences peuvent parfois s'exclure mutuellement. Il est courant,
du moins au départ, d'avoir des exigences conflictuelles. Classer les exigences par ordre d'importance vous aidera à
résoudre ces conflits.
|
Identification des processus et des unités d'exécution
Objet
|
Définir les processus et unités d'exécution qui existeront dans le système.
|
L'approche la plus simple consiste à attribuer tous les objets actifs à une unité d'exécution ou un processus commun
et à utiliser un simple ordonnanceur d'objets actifs, ce qui permet de minimiser la surcharge due au changement de
contexte. Cependant, dans certains cas, il peut s'avérer nécessaire de répartir les objets actifs sur un ou plusieurs
processus ou unités d'exécution. Ce sera très probablement le cas pour les systèmes en temps réel, où les capsules
utilisées pour représenter les unités d'exécution logiques doivent parfois répondre à des exigences strictes en matière
d'ordonnancement.
Si un objet actif qui partage une unité d'exécution de système d'exploitation avec d'autres objets actifs effectue un
appel synchrone à un autre processus ou unité d'exécution, et que cet appel bloque l'unité d'exécution partagée, tous
les autres objets actifs situés dans le processus appelant seront automatiquement suspendus. Cependant, un appel
synchrone du point de vue de l'objet actif peut être traité de manière asynchrone par l'ordonnanceur qui contrôle le
groupe d'objets actifs : celui-ci suspend l'objet actif appelant (qui attend l'achèvement de son appel synchrone), puis
ordonnance l'exécution d'autres objets actifs.
Au terme de l'opération "synchrone" initiale, l'objet actif appelant peut être repris. Toutefois, cette approche peut
parfois se révéler impossible. En effet, il arrive que l'ordonnanceur ne puisse être conçu pour intercepter tous les
appels synchrones avant leur blocage. Notez que l'ordonnanceur peut généralement traiter de la même manière un appel
synchrone entre des objets actifs qui utilisent le même processus ou la même unité d'exécution de système
d'exploitation (l'effet équivaut à celui d'un appel de procédure pour l'objet actif appelant).
En conclusion, les objets actifs devraient être regroupés dans les processus ou unités d'exécution selon la nécessité
qu'ils ont d'être exécutés en concurrence avec des appels synchrones qui bloquent l'unité d'exécution. En d'autres
termes, un objet actif partage le même processus ou la même unité d'exécution qu'un autre objet qui utilise des appels
synchrones bloquants, seulement s'il n'a pas besoin d'être exécuté en concurrence avec cet objet et s'il peut tolérer
la suspension de son exécution pendant le blocage de l'autre objet. Ainsi, dans une situation extrême, lorsque la
réactivité est critique, il peut être nécessaire d'attribuer chaque objet actif à une seule unité d'exécution ou un
seul processus.
Dans les systèmes en temps réel, lorsque les interfaces des capsules utilisent des messages, il est plus simple de
concevoir un ordonnanceur qui garantisse, au moins pour les communications entre capsules, l'absence de blocage des
unités d'exécution de système d'exploitation, même lorsqu'une capsule communique de manière synchrone avec une autre
capsule. Cependant, une capsule peut toujours émettre une requête qui bloquerait l'unité d'exécution directement au
système d'exploitation (par exemple, une requête de temps d'attente synchronisée). Pour les services de niveau
inférieur appelés par les capsules, il est nécessaire d'établir des conventions qui permettent d'éviter ce
comportement, si les capsules doivent partager une unité d'exécution commune (et utiliser un simple ordonnanceur pour
simuler les accès concurrents).
En règle générale, dans les situations ci-dessus, il est préférable d'utiliser des unités d'exécution, plus légères,
plutôt que des processus complets, puisque ces premières amoindrissent la surcharge. Malgré cela, il se peut que vous
souhaitiez tirer parti de quelques caractéristiques spéciales des processus dans certains cas spécifiques. Puisque les
unités d'exécution partagent le même espace adresse, elles sont par nature plus risquées que les processus. Si
l'éventualité d'un écrasement accidentel pose problème, il faut préférer les processus. De plus, étant donné que les
processus représentent des unités de récupération indépendantes dans la plupart des systèmes d'exploitation, il peut
être utile d'attribuer des objets actifs aux processus en fonction de la nécessité qu'ils ont d'être récupérés
indépendamment l'un de l'autre. En d'autres termes, tous les objets actifs qui doivent être récupérés ensemble, en tant
qu'unité, peuvent être réunis dans le même processus.
Pour chaque flux de contrôle différent requis par le système, créez un processus ou une unité d'exécution (processus
léger). Une unité d'exécution doit être utilisée lorsque des flux de contrôle imbriqués sont requis (c'est-à-dire s'il
est nécessaire, dans un processus, d'avoir un flux de contrôle indépendant au niveau de la sous-tâche).
Par exemple, des fils de contrôle séparés peuvent être utilisés pour effectuer les actions suivantes :
-
Séparer les domaines entre différentes zones du logiciel
-
Tirer parti des processeurs multiples dans un noeud ou des noeuds multiples dans un système distribué
-
Augmenter l'utilisation de l'unité centrale en attribuant des cycles à d'autres activités lors de la suspension
d'un fil de contrôle
-
Classer les activités par priorité
-
Autoriser le partage des charges entre plusieurs processus et processeurs
-
Accroître la disponibilité du système grâce aux processus de secours
-
Prendre en charge le SGBD, le gestionnaire de transactions ou d'autres sous-systèmes importants.
Exemple
Dans un guichet automatique, il est nécessaire de gérer des événements asynchrones provenant de trois sources
différentes : l'utilisateur du système, les périphériques du guichet automatique (lors d'un bourrage dans le
distributeur de billets, par exemple) ou le réseau (dans le cas d'une instruction de fermeture venant du réseau). Pour
ce faire, nous pouvons définir trois unités d'exécution séparées au sein du guichet, comme dans l'illustration
ci-dessous, à l'aide des classes actives du langage UML.
Processus et unités d'exécution dans le guichet automatique
|
Identification des cycles de vie des processus
Objet
|
Identifier les instants de création et de destruction des processus et fils de contrôle.
|
Chaque processus ou fil de contrôle doit être créé et détruit. Dans une architecture monoprocessus, la création du
processus s'opère au démarrage de l'application, et la destruction du processus à l'arrêt de l'application. Dans les
architectures multiprocessus, de nouveaux processus (ou unités d'exécution) sont générés par le processus initial, ou
naissent à partir du dédoublement de ce processus créé par le système d'exploitation au démarrage de l'application. Ces
processus doivent également être explicitement détruits.
Il est nécessaire de déterminer et de documenter la séquence d'événements qui conduit à la création ou à la destruction
d'un processus, ainsi que le mécanisme de création et de suppression.
Exemple
Dans le guichet automatique, un processus principal, chargé de coordonner le comportement de tout le système, est
démarré. Il génère à son tour un certain nombre de fils de contrôle subordonnés afin de surveiller divers éléments du
système : les périphériques du système et les événements émanant du client et du réseau. La création de ces processus
et fils de contrôle peut être illustrée à l'aide des classes actives du langage UML, et la création des
instances de ces classes actives peut être représentée par un diagramme de séquence, comme dans l'exemple ci-dessous :
Création de processus et de fils de contrôle lors de l'initialisation du système
|
Identification des mécanismes de communication interprocessus
Objet
|
Identifier les moyens de communication utilisés par les processus et unités d'exécution.
|
Les mécanismes de communication interprocessus (IPC) permettent l'envoi de messages entre des objets exécutés dans
différents processus.
Les mécanismes courants de communication interprocessus sont les suivants :
-
La mémoire partagée, avec ou sans sémaphore pour assurer la synchronisation
-
Les rendez-vous, en particulier lorsque la prise en charge est assurée directement par un langage tel qu'Ada
-
Les sémaphores, utilisés pour bloquer les accès simultanés à des ressources partagées
-
L'envoi de messages, point à point et point-multipoint
-
Les boîtes aux lettres
-
Les appels RPC (appels de procédure éloignée)
-
La diffusion d'événements, à l'aide d'un "bus logiciel" ("architecture de bus de messages")
Le choix d'un mécanisme IPC influera sur la modélisation du système. Dans une "architecture de bus de messages", par
exemple, il n'est pas nécessaire de définir des associations explicites entre les objets pour envoyer des messages.
|
Attribution des ressources de coordination entre processus
Objet
|
Attribuer les ressources rares.
Anticiper et gérer les potentiels goulots d'étranglement concernant les performances.
|
Les mécanismes de communication interprocessus sont généralement rares. La taille et le nombre des sémaphores, de la
mémoire partagée et des boîtes aux lettres sont habituellement fixes et ne peuvent s'accroître sans coût important. De
leur côté, les appels RPC, les messages et les diffusions d'événement absorbent la bande passante du réseau, qui est de
moins en moins disponible. Lorsque le système excède un certain seuil de ressources, ses performances se dégradent
généralement de manière non linéaire : lorsqu'une ressource rare est épuisée, les requêtes suivantes la concernant sont
susceptibles de produire des effets désagréables.
Si des ressources rares sont indisponibles, vous devez envisager plusieurs stratégies :
-
diminution du besoin de la ressource rare par la réduction du nombre de processus
-
modification de l'utilisation des ressources rares (pour un ou plusieurs processus, choisissez une ressource
différente, moins rare, à utiliser pour le mécanisme IPC)
-
augmentation de la quantité de la ressource rare (par exemple, augmentation du nombre de sémaphores). Cette
stratégie peut être adoptée pour des changements relativement petits, mais possède souvent des effets secondaires
ou des limites fixes.
-
partage de la ressource rare (par exemple, attribution de la ressource en cas de nécessité uniquement, puis abandon
de cette ressource après utilisation). Cette stratégie coûte cher et risque de se limiter à freiner la crise des
ressources.
Quelle que soit la stratégie choisie, le système devrait se dégrader en douceur (plutôt que de tomber en panne) et
fournir un retour d'informations approprié à un administrateur système pour permettre (si possible) la résolution de
l'incident sur le terrain, une fois le système déployé.
Si le système nécessite une configuration spéciale de l'environnement d'exécution (souvent contrôlée par la
reconfiguration du noyau du système d'exploitation) afin d'augmenter la disponibilité d'une ressource critique,
l'installation du système doit l'effectuer automatiquement ou demander à un administrateur système de l'effectuer pour
que le système puisse être opérationnel. Par exemple, il peut être nécessaire de redémarrer le système pour que le
changement prenne effet.
|
Mappage des processus dans l'environnement d'implémentation
Objet
|
Mapper les "flux de contrôle" aux concepts pris en charge par l'environnement d'implémentation.
|
Les processus conceptuels doivent être mappés à des constructions spécifiques dans l'environnement d'exploitation. De
nombreux environnements offrent plusieurs choix de types de processus, et généralement, permettent tout au moins
l'utilisation de processus et d'unités d'exécution. Les choix seront effectués en fonction du degré de couplage (les
processus sont autonomes, tandis que les unités d'exécution sont exécutées au sein d'un processus) et des exigences
liées aux performances du système (la communication interprocessus entre les unités d'exécution est généralement plus
rapide et plus efficace que la communication entre les processus).
De nombreux systèmes peuvent contenir un nombre maximal d'unités d'exécution par processus ou de processus par noeud.
Il se peut que ces limites ne soient pas absolues, mais imposées par la disponibilité des ressources rares. Les unités
d'exécution et processus déjà exécutés sur un noeud cible doivent être pris en compte au même titre que les unités
d'exécution et processus suggérés dans l'architecture de processus. Au terme du mappage, il faut également tenir compte
des résultats de l'étape précédente, Attribution des
ressources de coordination entre processus, afin de s'assurer qu'un nouveau problème de performances n'est pas en
train d'apparaître.
|
Mappage des éléments de conception aux fils de contrôle
Objet
|
Déterminer les fils de contrôle dans lesquels les classes et sous-systèmes de contrôle doivent être
exécutés.
|
Les instances d'une classe ou d'un sous-système donné doivent être exécutées dans au moins un fil de contrôle
qui fournit l'environnement d'exécution pour la classe ou le sous-système ; elles peuvent être exécutées dans plusieurs
processus différents.
En adoptant simultanément deux stratégies différentes, nous déterminons le "bon" nombre d'accès concurrents et
définissons le "bon" ensemble de processus :
De l'intérieur vers l'extérieur
-
A partir du modèle de conception, regroupez les classes et sous-systèmes dans des ensembles d'éléments coopérants
qui (a) coopèrent de près l'un avec l'autre et (b) doivent être exécutés dans le même fil de contrôle. Prenez en
compte l'effet produit par l'introduction d'une communication interprocessus au milieu d'une séquence de messages
avant la séparation des éléments dans différents fils de contrôle.
-
A l'inverse, séparez les classes et sous-systèmes qui n'interagissent pas du tout entre eux, en les plaçant dans
des fils de contrôle différents.
-
Ce groupement doit se poursuivre jusqu'à ce que le nombre de processus soit réduit au minimum, tout en permettant
encore la distribution et l'utilisation des ressources physiques.
De l'extérieur vers l'intérieur
-
Identifiez les stimuli externes auxquels doit répondre le système. Définissez un fil de contrôle à part pour
traiter chaque stimulus et un fil de contrôle de serveur à part pour fournir chaque service.
-
Prenez en compte l'intégrité des données et les contraintes liées à la sérialisation afin de réduire l'ensemble
initial de fils de contrôle et d'atteindre le nombre de fils qui peut être pris en charge par l'environnement
d'exécution.
Ce processus déterministe, non linéaire, conduit à une vue de processus optimale ; il nécessite peu d'itérations pour
atteindre un compromis acceptable.
Exemple
Le diagramme suivant illustre la répartition des classes, dans le guichet automatique, entre les processus et fils de
contrôle du système.
Mappage des classes aux processus dans le guichet automatique
|
|
Plus d'informations
Concepts |
|
Instructions |
|
Guides d'utilisation de l'outil |
|
© Copyright IBM Corp. 1987, 2006. All Rights Reserved.
|
|