Suivez-nous sur X

|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Dossier : Les bases du multitâche au niveau d'Exec
(Article écrit par Leo Schwab et extrait d'Amiga News Tech - septembre 1991)
|
|
Cet article est la traduction d'un article de Leo L. Schwab, préalablement posté sur le Programmer's
Network, rubrique Amiga Conference, du BBS WELL. Leo Schwab est l'auteur de nombreux programmes du
domaine public (Fred Fish lui doit beaucoup !) et l'un des programmeurs Amiga les plus prolifiques.
On lui doit notamment The Animation Studio de Walt Disney Software.
John Drapper disait qu'un moyen de devenir célèbre était d'écrire des manuels destinés à aider les programmeurs
débutants à mieux comprendre leur système. Ceci est donc ma tentative de démonstration des principes de base
du multitâche sur l'Amiga. Cet article décrit le multitâche au niveau d'Exec, sans parler du tout du DOS.
Personnellement, je préfère éviter le DOS autant que possible pour me concentrer sur Exec. Cela n'engendre
aucune difficulté supplémentaire, bien au contraire ; en fait, cela évite pas mal de maux de tête... Cet article
sera principalement pratique, et assumera que le lecteur a déjà quelques connaissances de bases sur le
principe du multitâche. Son but est principalement de vous aider à créer plusieurs tâches concurrentes et
complémentaires. Alors prenez votre compilateur favori et suivez le guide...
Introduction
La première chose à faire lorsque l'on s'intéresse au système de l'Amiga est d'oublier tout ce que l'on peut
déjà savoir sur d'autres systèmes multitâches. Particulièrement Unix. Exec sur Amiga n'a rien à voir avec
la plupart des autres systèmes multitâches, à l'exception peut-être de XINU (il existe un excellent livre sur
XINU, dont beaucoup de concepts peuvent s'appliquer à Exec).
Exec est à mon sens un fourre-tout du multitâche. Vous y trouverez tout ce qu'il vous faut pour faire ce
dont vous avez besoin, mais pas tout ce que vous voulez. Par exemple, il ne libérera pas toutes les
ressources que vous avez ouvertes, et sa manière de gérer les programmes "fous" n'est pas vraiment celle
que l'on est en droit d'espérer.
En revanche, Exec est petit et compact. Il est écrit en langage machine extrêmement optimisé. Parce
qu'il est petit et rapide et qu'il ne fait rien sans qu'on le lui demande. Exec est un système d'exploitation
temps réel capable de réagir aux interruptions et aux signaux très efficacement. Donc, en échange de devoir
tout faire par soi-même, on a un système multitâche très performant.
Pour commencer
Une tâche, au sens Exec du terme, est divisée en deux parties : du code résident quelque part en mémoire et
un bloc de contrôle faisant partie d'une liste chaînée de toutes les tâches gérées par Exec. Le segment
de programme peut être n'importe quoi n'importe où ; un moyen bête d'en créer un est tout simplement de déclarer
une fonction C :
Le bloc de contrôle de la tâche est une zone de mémoire qui décrit la tâche pour Exec. En particulier, il renseigne
sur la position et la taille de votre pile, quels signaux votre tâche a reçus et lesquels elle attend,
etc. Chaque tâche possède son propre bloc de contrôle.
De plus, toutes les tâches ont besoin d'une pile.
Même si vous n'appelez aucune sous-routine et ne disposez pas de variables locales, une pile est nécessaire à
Exec pour sauvegarder les registres du processeur en cas de changement de contexte (c'est-à-dire d'arrêt de
votre tâche au profit d'une autre). La taille minimum requise pour la pile est de 70 octets (Cf. RKM volume 1. page
1-17 et 1-18). Un chiffre rond et sûr est de 1 ko. Personnellement, je préfère utiliser des piles d'au moins
2 ko pour mes programmes, juste pour être sûr d'avoir assez d'espace pour tous les appels de sous-routines que
je peux effectuer et pour toutes les variables locales. La pile peut être dynamiquement allouée avec AllocMem().
Il est recommandé, mais non nécessaire, de ne pas préciser MEMF_PUBLIC dans ce cas.
Donner vie à une tâche
La bibliothèque de gestion d'Exec contient une fonction très pratique de création de tâche, baptisée
(assez justement) CreateTask(). Celle-ci ne réalise que les opérations de base de l'initialisation de
la tâche. Elle alloue d'abord de la mémoire pour la pile de la nouvelle tâche et son bloc de contrôle,
puis initialise les champs tc_SPUpper, tc_SPLower et tc_SPReg de cette structure, ainsi que tc_Node.ln_Pri,
tc_Node.ln_Type et tc_Node.ln_Name, avant d'appeler AddTask() et de vous retourner un pointeur sur le
bloc de contrôle nouvellement créé. Si la moindre erreur survient, CreateTask() retourne un pointeur
NULL et n'alloue aucune mémoire.
Le format d'appel de CreateTask() est le suivant :
"nom" est une chaîne de caractère qui définit le nom de votre tâche ; il sera utilisé si une
autre tâche désire trouver la vôtre.
"priorité" représente la priorité de votre tâche par rapport aux autres présentes dans le système.
Il s'agit d'un octet signé (de -128 à +127). 0 est la priorité normale.
"initPC" est la valeur initiale du PC. Généralement, ce sera un pointeur sur une fonction, ou quelque
chose dans ce genre.
"taille_pile" définit à la fois la taille de votre pile et de votre bloc de contrôle. CreateTask() alloue
"taille_pile" octets de mémoire et utilise les sizeof(struct_Task) premiers pour le bloc de contrôle,
le reste étant effectivement utilisé en tant que pile pour votre tâche. Ceci est important à savoir si
vous désirez une pile d'une taille bien particulière.
Le code source de CreateTask() se trouve dans le RKM volume 2, quelques pages après la page E-78,
dans l'appendice F.
Un appel typique à CreateTask() ressemble à ceci :
Notez bien que CreateTask n'effectue que l'initialisation de base de la tâche. Si vous désirez effectuer
des opérations spéciales, comme le traitement d'exceptions ou des interruptions. CreateTask() ne suffit plus,
vous devrez créer votre propre CreateTask(). Le code source du RKM fournit un bon exemple de la manière de s'y prendre.
|