FR 2821183 A1 20020823 FR 0102192 A 20010216 PROCEDE DE TRADUCTION D'UN CODE SOURCE L'invention est du domaine général des procédés pour machines informatiques. Plus spécifiquement, elle a trait au mode d'exécution d'applications dans un système informatique dit multi-applicatif ou multi-tâches sur lequel sont exécutées plusieurs applications. Elle concerne encore plus particulièrement un procédé de traduction d'un code source permettant de créer des applications logicielles tel que des sous-ensembles de ces applications soient adaptés à être exécutés dans différents contextes de données stockés dans ces différentes applications, et ce éventuellement d'une façon dépendante de l'état instantané des ressources du système. De façon connue, un tel système informatique multi-applicatif comporte un processeur central de traitement et une mémoire vive, auxquels sont reliés un certain nombre d'interfaces de périphériques, à travers une architecture de communication principale (bus). On rappelle que dans une tel système, le processeur exécute un code formé d'instructions logicielles, ledit code comprenant une première partie dite système d'exploitation, et au moins une seconde partie dite application. Dans le cas de machine multi-tâches, le processeur exécute plusieurs applications dites concurrentes (par exemple traitement de texte, navigateur Internet, logiciel de dessin), en exécutant successivement des soustâches de chacune des applications, ce qui donne une impression de traitement simultané ou parallèle des applications. La partie logicielle qui est exécutée sur le système informatique précédent se compose donc en outre d'un système d'exploitation (capable de gérer et exploiter les ressources du système informatique) comportant un ensemble d'éléments (tel qu'un pilote de périphérique) correspondants à des services de ressources externes gérés par le système d'exploitation selon les requêtes d'un ensemble d'applications exécutées par le (ou les) processeur. Afin de permettre à l'ensemble des applications de s'exécuter sur le processeur, le système d'exploitation joue le rôle d'ordonnanceur, c'est-à- dire qu'il choisit à quel instant chaque application doit être exécutée. Les applications peuvent influencer l'ordonnanceur en spécifiant des paramètres comme leur priorité par rapport aux autres applications ou encore les contraintes temps réel d'attribution du processeur. Pour la suite du texte, on définit les termes suivants : Une application, telle qu'un traitement de texte par exemple, comporte une ou plusieurs tâches : par exemple affichage écran des données tapées, sauvegarde régulière du document. Chacune de ces tâches (en anglais process ) correspond à un espace d'adressage de mémoire (la mémoire disponible étant partagée de façon sécurisée en parts de ressource mémoire entre les applications utilisatrices). Une tâche contient à la fois : 1/des données (ou plus précisément une adresse virtuelle associée à une zone de mémoire physique contenant des données. Une telle association est connue sous le nom de mappage), 2/et du code informatique correspondant à la tâche (par exemple code de sauvegarde régulière du contenu d'un document créé sur un traitement de texte vers un disque externe). L'ensemble des données contenues à un instant donné dans une tâche forme un contexte. Ce contenu évolue au fur et à mesure que des opérations sont effectuées sur ces données, selon les commandes adressées au processeur et définies dans le code informatique. Un code informatique est une liste de commandes exécutables par un processeur, stockée dans un dispositif de mémoire de la machine informatique (mémoire de type disque dur lorsque l'application n'est pas exécutée, et mémoire vive RAM lorsque l'application est en cours d'exécution). Un fil d'exécution, également nommé ligne (par dérivation du concept de ligne de code informatique), élément de code logiciel, fil de contrôle, ou processus léger ( thread en anglais), correspond à l'abstraction de la ressource processeur (qui est vis à vis d'une application une ressource de travail, au même titre qu'une ressource mémoire). Un fil d'exécution est donc un ordre de haut niveau adressé à la ressource processeur (par opposition aux ordres immédiatement compréhensibles par le processeur en langage machine). On définit la migration d'un code d'une première tâche (espace mémoire d'une application) vers une seconde tâche, comme l'exécution du code informatique, originellement associé aux données de la première tâche, sur les données du contexte de la seconde tâche. On rappelle pour la suite de la description que, dans le domaine de la programmation dite par objets , on définit une classe d'objets par des attributs (exemple couleur, taille) et des méthodes (fonctions effectuées par l'objet). Chaque mise en oeuvre de la classe s'appelle une instance de la classe, ou un objet. Une application écrite en programmation objet fait donc appel à un certain nombre d'objets logiciels. Afin d'améliorer l'intégrité d'une telle architecture logicielle, c'est à dire d'éviter les risques d'interférences entre les différentes applications lorsqu'elles manipulent des registres de la mémoire du système informatique, un système de protection mémoire est ajouté à cette architecture et mis en oeuvre par le système d'exploitation. Ainsi, une première application ne peut pas modifier les données de la tâche d'une seconde application. De même, une application ne peut pas, directement, utiliser les ressources matérielles comme la carte réseau. Si cette application veut utiliser une ressource matérielle, elle doit émettre une demande au système d'exploitation, et, dans celui-ci, à l'élément compétent (le pilote réseau dans cet exemple), qui seul peut accéder en lecture ou écriture aux registres de l'interface physique du périphérique. Un tel schéma de protection mémoire est indispensable afin de préserver l'intégrité de l'architecture logicielle, c'est à dire de limiter les interférences conflictuelles possibles entre les différents composants logiciels (applications, pilotes et système d'exploitation) entrant en jeux. Dans la plupart des systèmes d'exploitation modernes, les fils d'exécution sont associés à leur tâche (par exemple les commandes processeur de haut niveau utilisées dans une tâche de sauvegarde régulière de document, dans une application de traitement de texte, sont associées de façon fixe à cette tâche). Or, il peut être souhaitable, pour la mise en oeuvre d'une première application, d'exécuter un code (outil logiciel) déjà existant dans une seconde application, dans un but de simplifier la création d'application et/ou de réduire l'occupation mémoire. Dans le cas où chaque fil d'exécution est associé à sa tâche, pour exécuter un fil d'exécution associé à une seconde tâche sur des données situées dans une première tâche en cours de traitement, il est nécessaire de créer un fil d'exécution supplémentaire dans la seconde tâche, puis d'utiliser un mécanisme de notification inter tâche, pour active ce fil d'exécution supplémentaire. Le principal inconvénient de cette solution réside dans la lourdeur du mécanisme de notification-qui engendre souvent un appel à l'ordonnanceur système-ainsi que dans la lourdeur du développement, puisqu'il est nécessaire lors de la programmation de prévoir la création d'un fil d'exécution supplémentaire à un endroit prédéterminé du code. Il existe donc un problème clairement identifié de migration de fil d'exécution (ou plus généralement de code) entre diverses tâches (application d'un même code à divers contextes successifs), cette migration n'impliquant pas l'ordonnanceur du système d'exploitation, et avec une simplicité de création et de mise en oeuvre. Une première possibilité réside dans la création d'un langage de programmation d'applications permettant de concevoir, dès leur création, des applications susceptibles d'échanger des fils d'exécution. Dans ce domaine, un article intitulé On migrating threads, Bemd Mathiske, Florian Matthes, Joachim w. Schmidt) paru dans le Journal of Intelligent Information Systems, 8 (2), pp. 167-191, 1997 , tente de définir un langage de programmation composé par des fils d'exécution qui peuvent migrer entre différents contextes. Dans ce document, la migration est faite à l'aide d'une primitive langage de la forme migrate to contexte do code end , qui permet d'exécuter le code dans un contexte différent. Il apparaît dans le texte que cette solution s'applique uniquement au calcul distribué (c'est à dire au calcul dans lequel plusieurs processeurs- éventuellement virtuels-travaillent chacun sur un ensemble de données) dans un but d'équilibrage de charge entre processeurs. D'abord, elle s'applique à un langage fonctionnel pour implémenter le modèle, et non aux langages impératifs (de type C), largement utilisés dans la majorité des applications. De plus, elle propose beaucoup plus qu'une simple migration puisque l'ensemble du contexte mémoire (variables locales, globales, pointées,...) est transféré de façon implicite, au lieu de transférer le seul fil d'exécution. Le programmeur ne dispose pas de contrôle lui permettant de restreindre le transfert à une partie du contexte. Le procédé transfère l'ensemble des variables pendant la migration et tous les accès sont cohérents. Dans un autre cadre, dans les langages de programmation par objet, on peut considérer que chaque objet représente un contexte (contenu d'une tâche) partiellement hermétique, dans le sens qu'i ! se comporte comme un boîte noire sur laquelle le programmeur n'a accès que dans son ensemble. Ainsi, pour faire une migration d'un objet vers un autre, il suffit, à partir d'un code écrit dans un objet quelconque, de spécifier le nom de l'objet postfixé par le nom de la méthode qui l'exporte. En terme de migration, cela revient à migrer temporairement vers le nouvel objet, le temps d'exécuter la méthode, puis de revenir vers le contexte initial. Ce modèle objet ne met en oeuvre qu'une protection d'intégrité système statique (effectuée lors de la compilation). De plus, le modèle objet ne permet d'exécuter qu'une méthode (parmi la liste prédéterminée des méthodes déclarées dans une classe donnée) dans le nouveau contexte et non un morceau de code de forme quelconque. Enfin, la migration pour les objets est strictement bilatérale, en ce qu'elle implique de revenir au contexte initial en fin d'exécution du code migrant. Dans un autre document intitulé Evoiving Mach 3.0 to a Migrating Thread Model, Bryan Ford, Jay Lepreau, University of Utah), Proceedings of the Winter 1994 USENIX Technical Conference and Exhibition, pp. 97-114, January 1994 , un modèle de fil d'exécution migrant proposé pour le système d'exploitation Mach est utilisé pour mettre en oeuvre une fonctionnalité dite d'appel de procédure à distance ( Remote Procedure Hall , RPC en anglais), et plus particulièrement un RPC local (c'est-à-dire que le contexte appelé se trouve sur le même processeur que le contexte de l'appelant). Cependant, on retrouve les même limitations que pour le modèle objet : solution bilatérale, pas de possibilité d'écrire un code arbitraire, mais seulement une méthode. Enfin, dans un système d'exploitation décrit dans le document Scout : A path based operating system, PhD Dissertation. David Mosberger Departement of Computer Science, University of Arizona (July 1997) , les fils d'exécution peuvent migrer de façon unilatérale entre des modules ou services d'une application. Ces modules, qui se comportent également comme des ensembles fermés (boîtes noires) peuvent être protégés dans des espaces d'adressage différents. Ce système propose donc des fils d'exécution pouvant migrer de façon unilatérale entre différents contextes. Cependant, comme pour le modèle objet ou pour l'appel de procédure à distance optimisé du système d'exploitation Mach, il n'est pas possible de migrer puis d'exécuter un code arbitraire. La seule possibilité après migration est d'exécuter une et une seule méthode qui est gérée par le logiciel du second contexte, et doit donc être programmée indépendamment du code réalisé dans le contexte initial. La présente invention a donc pour objet de résoudre les problèmes précédemment cités. La présente invention a plus particulièrement pour objet un procédé de traduction d'un code source vers un code produit, les codes étant écrits dans un langage informatique permettant de décrire au moins une tâche, à laquelle sont associés une première méthode, un premier contexte mémoire et un code informatique, le code produit pouvant être exécuté dans un environnement multi-tâches avec gestion de mémoire virtuelle, le procédé étant caractérisé en ce qu'il comporte une étape de migration comportant les sous- étapes suivantes : - recherche dans ledit code source d'une instruction et de ses paramètres, l'instruction représentant un ordre de migration du premier contexte, vers un nouveau contexte associé à une tâche cible, pour l'exécution d'une partie de la première méthode de la tâche ; et - transformation du code source en code produit fonctionnellement équivalent, tel que la partie soit exécutable au sein du nouveau contexte. Corrélativement, l'invention a pour objet un dispositif de traduction d'un code source vers un code produit, les codes étant écrits dans un langage informatique permettant de décrire au moins une tâche, à laquelle sont associés une première méthode, un premier contexte mémoire et un code informatique, le code produit pouvant être exécuté dans un environnement multi-tâches avec gestion de mémoire virtuelle, le dispositif étant caractérisé en ce qu'il comporte : - des moyens de recherche dans le code source d'une instruction et de ses paramètres, l'instruction représentant un ordre de migration du premier contexte, vers un nouveau contexte associé à une tâche cible, pour l'exécution d'une partie de ladite première méthode de la tâche ; et -des moyens de transformation du code source en code produit fonctionnellement équivalent, tel que la partie soit exécutable au sein du nouveau contexte. Cette propriété permet d'autoriser un fil d'exécution ou du code informatique de forme arbitraire à migrer à travers les différentes tâches, sans intervention de l'ordonnanceur système. Cette propriété permet également une migration unilatérale, du contexte de la tâche vers celui de la tâche cible. Selon une caractéristique particulière, l'ordre de migration comporte en outre des paramètres correspondants à des variables transférées au cours de la migration du premier contexte vers le nouveau contexte. Ceci permet au programmeur de spécifier les variables mémoire qu'il veut transférer entre différentes tâches. Selon une autre caractéristique particulière, le procédé de traduction selon l'une quelconque des revendications comporte également une étape de vérification de l'intégrité dudit code source. Ceci permet de s'assurer qu'une tâche particulière ne modifie pas les données d'une autre tâche, ce qui assure l'intégrité de l'architecture logicielle, après le changement de contexte. L'invention vise également un dispositif qui comporte des moyens adaptés à mettre en oeuvre un procédé de traduction tel que décrit ci-dessus. L'invention vise également un compilateur qui comporte un dispositif de traduction tel que décrit ci-dessus. L'invention vise par ailleurs un moyen de stockage d'informations, éventuellement totalement ou partiellement amovible, lisible par un ordinateur ou un processeur contenant des instructions d'un programme d'ordinateur, permettant la mise en oeuvre d'un procédé de traduction tel que décrit cidessus. L'invention vise également un programme d'ordinateur chargeable dans un appareil programmable, comportant des séquences d'instructions ou des portions de code logiciel pour mettre en oeuvre les étapes d'un procédé de traduction tel que décrit ci-dessus, lorsque ce programme d'ordinateur est exécuté sur un appareil programmable. Les avantages et caractéristiques particulières propres au dispositif, au compilateur, ainsi qu'aux moyens de stockage d'informations et au programme d'ordinateur étant les mêmes que ceux exposés ci-dessus concernant le procédé de traduction selon l'invention, ils ne seront pas rappelés ici. D'autres aspects et avantages de la présente invention apparaîtront plus clairement à la lecture de la description de modes particuliers de réalisation qui va suivre, cette description étant donnée uniquement à titre d'exemple non limitatif et faite en référence aux dessins annexés sur lesquels : - la figure 1 représente l'architecture matérielle d'un microordinateur adapté à mettre en oeuvre un protocole de traduction selon l'invention ; - le figure 2 représente de façon schématique l'architecture logicielle d'un micro-ordinateur conforme à la figure 1 ; - la figure 3 est un exemple de code migrant au sens de l'invention ; - ! a figure 4 est un exemple de modèle de tâche utilisée dans l'invention ; -la figure 5 illustre le mécanisme de transformation de code pour la migration inter-tâche ; - la figure 6 illustre le mécanisme de transfert de données au cours d'une migration selon l'invention ; - la figure 7 illustre un premier mécanisme de migration d'instructions composées selon l'invention ; - la figure 8 illustre un second mécanisme de migration d'instructions composées selon l'invention ; - la figure 9 est un exemple de code de surtypage selon l'invention ; -la figure 10 est un exemple de code de partage de tâche selon l'invention ; - ! a figure 11 est un exemple de code utilisant la notion de privilège selon l'invention ; -la figure 12 représente un algorithme de transformation du code source en code produit selon l'invention ; - la figure 13 représente un algorithme de l'ordre de migration selon l'invention ; et - la figure 14 représente un algorithme utilisé pour revenir au contexte initial dans le cas d'une migration avec retour selon l'invention. L'invention est un procédé de traduction (sous la forme d'un compilateur, d'un pré-processeur ou un exécutable) qui permet de préparer dès leur programmation des applications logicielles pour leur permettre d'utiliser des codes migrants. On utilisera dans la suite de la description le terme de compilateur pour désigner l'outil mettant en oeuvre) le procédé selon l'invention. Ces applications sont destinées à être exécutées sur des ordinateurs de type PC utilisant un système d'exploitation multi-tâches avec gestionnaire de mémoire virtuelle (ce qui est le cas le plus général des systèmes d'exploitation actuels pour ordinateurs de type PC). Dans le cadre de la présente description, ces applications sont destinées à être utilisées sur un système informatique utilisant un système d'exploitation de type Chorus. Les exemples de code produit fournis sont donc adaptés à ce type de système d'exploitation. Une adaptation à un autre système d'exploitation est réalisable par l'homme du métier. De façon résumée, un programmeur souhaitant développer une application utilisant une logique de migration de fils d'exécution, écrit le code source de cette application à l'aide d'un langage de programmation comportant une ou des instructions spécifiques. Ce code source est traduit par le compilateur (ou pré-processeur) mettant en oeuvre le procédé selon l'invention en un code produit qui respecte les fonctionnalités de migration souhaitées par le programmeur, et qui est compatible avec le système d'exploitation de la machine sur laquelle doit être exécutée l'application (Chorus dans le présent exemple non limitatif). La figure 1 représente, de façon générale, l'architecture matérielle d'un micro-ordinateur 50 adapté à mettre en oeuvre le procédé de traduction selon l'invention. Le micro-ordinateur 50 est par exemple de type PC. Le micro-ordinateur 50 comporte une unité centrale 100 (notée CPU sur la figure 1), par exemple un processeur de type Pentium, laquelle exécute les instructions relatives à la mise en oeuvre de l'invention, lesdites instructions étant stockées dans une mémoire morte (ROM) 102 ou dans d'autres éléments de stockage. Ce micro-ordinateur 50 possède des moyens classiques (matériels et/ou logiciels) de gestion de mémoire virtuelle, connu de l'homme de l'art. Une architecture de communication 101 (par exemple sous la forme d'un bus) permet la communication entre les différents sous-éléments (écran 104, clavier 105, disque dur 106, lecteur de disquettes 107, etc. ) du micro-ordinateur 50 ou liés à lui. La représentation de l'architecture de communication 101 n'est naturellement pas limitative, et notamment l'unité centrale 100 est susceptible de communiquer des instructions ou des données à tout sous-élément du micro-ordinateur 50 directement ou par l'intermédiaire d'un autre sous-élément du micro-ordinateur 50. Après la mise sous tension, une mémoire vive (RAM) 103 contient le code exécutable du procédé selon l'invention ainsi que les variables nécessaires à la mise en oeuvre de l'invention. Cette mémoire vive 103 contient également les informations qu'un client souhaite transférer de l'espace d'adressage d'une application ou du système d'exploitation vers l'espace d'adressage d'une autre application. Ces informations peuvent être produites et placées en mémoire par les applications elles-mêmes durant leur exécution ou par tout sous-élément du micro-ordinateur 50, comme par exemple une interface de communication 109 vers un réseau 110. La figure 2 représente, de façon générale, l'architecture logicielle 200 du micro-ordinateur 50 décrit en référence à la figure 1. L'architecture logicielle 200 comporte un système d'exploitation 210, le système d'exploitation 210 comportant lui-même divers pilotes de périphériques 211,212, 213 permettant de contrôler respectivement les ressources matérielles 104,109 et 106 décrites en référence à la figure 1. Elle comporte également des applications 221,222 concurrentes dont l'ordonnancement est géré, en particulier, par un ordonnanceur du système d'exploitation non représenté ici. La figure 3 est un ensemble de code migrant au sens de l'invention. Le programme listé s'exécute à l'intérieur d'un fil d'exécution quelconque, dans une tâche A quelconque. Pour la mise en oeuvre du procédé selon l'invention, c'est à dire la préparation d'applications adaptées à utiliser des éléments de code migrant, on écrit le code source du programme desdites applications en utilisant un langage impératif du type C (non limitativement) auquel on adjoint une instruction nouvelle spécifique, de la forme switch to BO)), où switch to est un mot clef du langage et Bo est un identificateur d'une tâche cible. L'utilisation de cette instruction est soumise à des règles restrictives détaillées ultérieurement en référence aux figures 7 et 8. Ainsi la première partie Code 1 du programme est exécutée normalement, dans le contexte A de la tâche AO. Puis, l'instruction switch to fait migrer le fil d'exécution courant vers le contexte B de la tâche cible BO. Enfin, la suite du programme Code 2 est exécutée, dans le fil d'exécution courant mais dans le contexte mémoire B de la tâche cible BO. On comprend que les applications sont donc écrites en utilisant, entre autres, l'instruction spécifique switch to , puis compilées et exécutées. Pour vérifier de façon statique (initiale) qu'après migration le code Code 2 n'accède qu'aux données appartenant au contexte cible B, un modèle similaire aux structures dites typées est utilisé. Pour ce faire, les contextes des tâches sont définis par le programmeur dans le code source comme des structures typées : structures de données suivant un modèle formalisé, dont les champs correspondent ici aux variables ou aux fonctions globale accessibles par tout code s'exécutant dans ce contexte. La figure 4 est un exemple de modèle de tâche utilisé par l'invention, basé sur la notion des classes des langages objets, telle C++. Dans cette figure, le mot clef Task est utilisé comme le mot clef Class du C++ pour introduire la déclaration d'une nouvelle tâche, suivi de l'identificateur typetâche de cette nouvelle tâche. Concernant les champs, on utilise dans le présent exemple cité, à titre non limitatif, un champ constructeur void createo et un champ destructeur void detete () , respectivement utilisés pour la création et la destruction des instances (c'est à dire des occurrences de traitement par le processeur) de la tâche déclarée. La figure 5 illustre le mécanisme de transformation de code pour la migration d'une tâche AO vers une tâche cible BO. Pour exécuter sur un système informatique le code produit d'une tâche AO utilisant une instruction spécifique switch to , tel que décrit en référence à la figure 3, on utilise une primitive système permettant à un fil d'exécution quelconque de migrer vers une tâche arbitraire, ainsi que des moyens système pour créer et détruire des tâches indépendantes. La primitive système est ici une ligne de programmation écrite par le programmeur, correspondant à une commande du système d'exploitation 210. Plus précisément, à partir d'un code source écrit par un utilisateur programmeur, ledit code source 1 comprenant une méthode appartenant à une tâche AO (comprenant une instruction switch to vers une tâche cible BO, comme illustré figure 3) constitué d'une première partie 2 de déclaration et de code, d'un ordre de migration 4 vers la tâche cible BO et finalement d'une deuxième partie 3 de code, ce code source 1 est transformé (par le compilateur) en un code produit. Le procédé de transformation comporte les étapes suivantes : -à partir de la méthode initiale du code source 1, la première partie 2 de code avant l'instruction de migration est conservée, et est suivie par un ordre de migration système 5. - une nouvelle méthode 6 est crée dans le contexte de la tâche cible BO vers laquelle doit s'effectuer la migration du fil d'exécution. Cette nouvelle méthode 6 ne contient que le code 7 correspondant à la seconde partie 3 du code de la méthode initiale du code source 1 exécuté après l'instruction de migration 4. - l'ordre de migration système 5 consiste en un appel de procédure à distance, dans le contexte de la tâche cible BO, vers la méthode 6 nouvellement crée dans ce contexte de la tâche cible BO. On crée ainsi, pour chaque application écrite en code source (de type C++) un fichier qui respecte la sémantique multi-contexte exprimée par le programmeur dans le code initial, à l'aide de l'instruction switch to . On peut alors utiliser pour la compilation des applications ainsi adaptées aux codes migrants un compilateur langage classique qui permet, d'une part, de transformer un programme source (lignes de code C++ par exemple) en un fichier exécutable compréhensible immédiatement par le processeur et, d'autre part, de vérifier que la sémantique du fichier source est correcte. Il est noté que si la seconde partie 3 de code qui suit l'instruction de migration 4 (aussi nommé ordre de changement de contexte) contient lui aussi un ordre de changement de contexte, alors cette opération de traduction du code source lui est également appliqué, de façon récursive. On obtient après transformation de l'ensemble des ordres de migration d'un code source 1 un nouveau fichier appelé code produit dont le code ne fait référence qu'à la tâche AO à laquelle il appartient, avec des ordres de migration système 5 pour changer de contexte et appeler une fonction appartenant à un contexte cible B (associé à une tâche cible B ()). Selon le procédé, on utilise les primitives système de migration et de création de tâche pour réaliser (transformer en code exécutable) la sémantique du code source initial. Pour vérifier initialement (avant la compilation et l'exécution) l'intégrité du code multi-contexte écrit par le programmeur, s'il n'utilise pas d'ordre de migration 4, il suffit de vérifier que les fonctions appartenant à une tâche donnée n'utilisent que les variables et les fonctions déclarées par cette tâche. C'est le principe de la vérification statique de code du modèle objet. Concernant la vérification des ordres de migration, après un ordre 4 de changement de contexte, la seconde partie 3 de code suivant cet ordre 4 ne peut avoir accès qu'aux variables et fonctions de la tâche cible BO. Concernant les variables locales de la méthode 1 initiale qui comporte l'instruction de migration 4, la seconde partie de code 3 après migration vers un contexte cible B ne peut accéder à ces variables lors de l'exécution, puisque ces données forment le contexte initial A stocké dans la tâche de départ AO qui n'est plus accessible (le fil d'exécution s'applique alors sur le contexte cible B) après changement de contexte. Ainsi, la vérification statique de l'intégrité du code source 1 comportant des ordres de migration 4 revient à vérifier de façon classique (selon le modèle objet) l'intégrité du code produit. La figure 6 illustre un mécanisme de transfert de données au cours d'un changement de contexte tel que décrit en référence à la figure 5. Tout comme les appels de procédure à distance permettent de transférer les paramètres de la fonction distante à appeler, le programmeur peut spécifier dans l'ordre de migration switch to les noms 8 des variables qu'il désire transférer. La méthode 6'générée dans la tâche cible BO aura alors pour argument 9 ces variables, et l'ordre de migration comportera les arguments 10 correspondants aux variables 8 spécifiées par le programmeur. La figure 7 illustre un premier mécanisme de migration d'instructions composées selon l'invention. Dans le cas du langage de programmation C, les instructions composées sont classiquement délimitées par des marqueurs {} . Pour de telles instructions en effet, les changements de contexte sont restreints, en ce sens, qu'un retour vers le contexte initial A, après exécution de ces instructions est obligatoire. Ainsi, par exemple, si un changement de contexte 4 vers un contexte cible B est exécuté dans une première branche d'une instruction conditionnelle de type if (expression) branche1 ; else branche2 , alors en restreignant un retour vers le contexte initial A à la fin de cette première branche, on est assuré que quelle que soit la valeur booléenne de l'expression, le contexte après exécution du if est toujours le contexte initial A. Plus précisément et comme illustré sur la figure 7, pour obliger ce retour vers le contexte initial A de façon automatique, on ajoute, lors de la compilation, un ordre de migration retour 11 switch back vers le contexte initial A, à la fin de chaque instruction composée 12 contenant un ou plusieurs ordres de migration 4a, 4b. En variante, comme illustré figure 8, un second mécanisme de migration d'instructions composées selon l'invention consiste à obliger le programmeur à spécifier, à chaque premier ordre de migration 4a'contenu dans une instruction composée 12', la portion de code 13 qu'il désire exécuter dans le contexte cible B de la tâche B (). Ensuite, à l'intérieur de cette portion de code 13, le programmeur peut utiliser des ordres de migration 4b'sans contrainte, tant qu'il ne déclare pas de nouvelle instruction composée (auquel cas, il devrait appliquer cette règle de façon récursive). Un exemple de modèle de tâche langage , une tâche langage étant écrite en code source de haut niveau par le programmeur, et associées au mot clef task a été défini en référence à la figure 4. De façon connue dans le cadre de la programmation par objets, chaque instanciation d'une tâche langage , occupe un espace d'adressage mémoire. Le mécanisme de migration tel que précédemment décrit ne pouvant s'appliquer directement à une tâche langage , le procédé de traduction propose en outre une étape de substitution (décrite à la figure 12) du code source qui remplace chaque début et fin d'utilisation d'un espace d'adressage mémoire spécifique à l'instanciation d'une tâche langage par un sous-programme ayant pour but, d'une part, de créer une nouvelle tâche système et, d'autre part, d'associer ladite instanciation de la tâche langage avec ladite nouvelle tâche système. Par exemple, une ligne de code Task tA A ())) dans le programme source est remplacée par un sous-programme mettant en oeuvre les étapes suivantes : - demande de création d'une tâche système au système d'exploitation 210 ; -allocation d'une portion de mémoire de la taille dudit espace d'adressage mémoire de la tâche langage A () et mappage dans ladite tâche système ; - association de ladite tâche langage A () avec ladite mémoire mappée. On note ici que ce sous-programme n'est pas exécuté par le compilateur, mais par le programme utilisateur lui-même. Le rôle du compilateur n'est donc ici que de substituer l'instanciation d'une tâche langage A () par un sous-programme, sous-programme qui sera transformé en code machine puis exécuté au sein de l'application. Il est important de noter qu'on autorise ici la migration vers des tâches qui ne sont connues qu'au moment de l'exécution et non pas à la compilation. La solution décrite précédemment fonctionne toujours dans ce cas, même pour la vérification statique de l'intégrité. En effet, si on utilise un langage typé (comme c'est le cas pour la plupart des langages impératifs tels le C), toute variable a un type. En particulier la variable qui sert à spécifier le contexte vers lequel le programmeur désire migrer possède un type. C'est ce type, qui doit bien évidement être celui d'une tâche, qui sert à vérifier l'intégrité statique du code. De plus, la possibilité de migration vers un contexte dynamique permet d'étendre la solution pour la déclaration des tâches avec du surtypage syntaxique (équivalent de l'héritage pour le modèle objet, mais sans possibilité de redéfinir des variables ou des méthodes). Dans l'exemple décrit en référence à la figure 9, le surtypage est associé au mot-clef extends du langage de programmation compris du compilateur. Ainsi, si une tâche de type tA étend en terme de fonctionnalité et de variables une tâche de type tB (on dit alors que tA est un surtype de t~B, ou encore que tA hérite de tB), alors tout ordre de migration vers l'instanciation d'une tâche de type tB peut être remplacé par la même migration avec l'instanciation d'une tâche de type tA, sans avoir à modifier le code produit ou à vérifier l'intégrité statique de code. Il a été décrit précédemment qu'une solution pour accéder aux données d'une tâche est d'y migrer temporairement. Dans le mode de réalisation décrit ici, le procédé de traduction selon l'invention, propose un mécanisme de partage inter-contexte, correspondant au mappage d'un contexte dans un autre. Par ce mécanisme il devient possible d'accéder à une tâche en lecture et/ou en écriture à partir d'une autre tâche. Ce mappage est en outre dynamique dans le sens où si un contexte évolue dynamiquement, alors le contexte qui le mappe accédera aussi à l'évolution du contexte, et non pas au contexte initial avant évolution. La figure 10 montrant un exemple de code de partage de tâche par mappage va maintenant être décrite. Dans l'exemple décrit ici, le mappage est symbolisé par le mot-clef maps du langage de programmation compris au compilateur. Les lignes 1 à 5 de la figure 10 correspondent à une déclaration de tâche comme décrit précédemment. La ligne 6 de la figure 10 correspond à la déclaration d'une autre tâche de type tB qui mappe une tâche de type tA précédemment déclarée à la ligne 1. Les deux tâches contiennent une variable de nom X (lignes 4 et 9 de la figure 10). Puis les lignes 11 à 15 de la figure 10 montrent un exemple d'une méthode de la tâche Bo. Les variables propres à la tâche de type tB sont directement référencées (ligne 13). Par contre, les variables de la tâche de type tA sont préfixées par a t~A (ligne 14) ce qui permet de les distinguer des variables propres. Enfin, à la ligne 17, la tâche Bo est instanciée à partir du type tB et mappe la tâche AO de type tA (ligne 16). En terme de traduction, le code de la ligne 17 de la figure 10 est transformé, par le compilateur selon le mécanisme de mappage, associé au mot clé maps du langage et qui comporte les étapes suivantes : - demande de création d'une tâche système au système d'exploitation ; - allocation d'une portion de mémoire de la taille dudit espace d'adressage mémoire de la tâche A() et mappage dans ladite tâche système ; - mappage de la mémoire associée à la tâche A() dans la tâche Bo ; et - association de l'espace d'adressage mémoire de la tâche A() avec cette mémoire mappée. On peut noter que par rapport aux étapes d'initialisation classique, seule l'étape de mappage à été rajoutée. Elle permet au code exécuté dans le contexte B de la tâche Bo de pouvoir accéder sans migration aux données de la tâche A(). D'autre part, la plupart des processeurs modernes offrent une notion de privilège c'est-à-dire qu'ils fonctionnent selon au moins deux modes de protection. Le niveau superviseur, qui possède le plus de contrôle sur le hardware, est souvent utilisé par le système d'exploitation, tandis que le niveau de privilège inférieur (dit niveau utilisateur) est utilisé par les applications. Dans l'invention, on propose au programmeur, quand il déclare les tâches, de spécifier si elles doivent s'exécuter en mode privilégié, en utilisant pour ce faire un mot-clef privi) edge Kernet . Des exemples de telles déclarations sont illustrées figure 11. La traduction de ces déclarations comporte les étapes suivantes : - demande de création d'un tâche de privilège superviseur au système d'exploitation ; - allocation d'une portion de mémoire de la taille dudit espace d'adressage mémoire de la tâche devant s'exécuter en mode privilégié et mappage dans ladite tâche système ; - association de l'espace d'adressage mémoire de la tâche devant s'exécuter en mode privilégié avec ladite mémoire mappée. Par rapport au schéma de traduction précédent, seule la première étape est modifiée, en demandant lors de la création de la tâche par la primitive système, que le privilège de la tâche soit du niveau superviseur. La figure 12 représente un algorithme de transformation du code source en code produit selon l'invention. Il permet, à partir du code source créé par le programmeur, d'obtenir un programme compatible avec le système d'exploitation sur lequel doit être exécutée l'application (Chorus dans le présent exemple). Ce système d'exploitation doit être de type multitâche, avec gestion de mémoire virtuelle (MMU en anglais). Il comprend principalement trois étapes successives. Dans une première étape E1, on transforme les occurrences des mots clés maps , extends et task , symbolisant respectivement les fonctions de surtypage, de partage intertâche et de tâche langage, en code produit modifié. Ces transformations réalisées dans des sous-étapes E11, E12, E13 peuvent être réalisées dans un ordre quelconque. Dans une étape E2, les instanciations des tâches et des tâches mappantes sont transformées en sous-programmes dans des sous-étapes de substitution E21 et de mappage E22. Dans une étape E3, les ordres de changement de contexte (instruction de migration switch to ), et les ordres de retour vers le contexte initial pour les instructions composées sont transformés dans des sous-étapes E31, E32. La figure 13 représente un algorithme de l'ordre de migration, basé sur le modèle de privilège des processeurs Intel X86, où chaque niveau de privilège possède sa propre pile. En particulier, cet algorithme repose sur le fait qu'il y ait deux piles distinctes, pour le mode superviseur et le mode utilisateur. Il comporte les sous-étapes E311 à E319 qui vont maintenant être décrites. E311. Depuis le code utilisateur, un appel système est fait, en passant comme arguments sur la pile utilisateur ceux de l'ordre de migration. La raison de cet appel système est de passer en mode privilégié, sans quoi il ne serait pas possible de changer le contexte mémoire courant. E312. Une fois en mode système, les arguments stockés sur la pile utilisateur sont recopiés vers la pile système. E313. Ce test dépend du type de migration qui est fait, à savoir selon qu'il y ait un retour vers le code initial ou non. E314. La référence de la pile, du contexte et de l'adresse de retour utilisateur sont stockés dans le contexte système. Cette opération permettra, par la suite, de restaurer le contexte initial, et donc de faire le retour vers le code initial. E315. La pile utilisateur est libérée car elle ne sera plus réutilisée. E316. Le nouveau contexte utilisateur est activé. Pour ce faire, le système doit récupérer la référence de la tâche système, stockée dans le champ taskjnfo. actor de la structure pointée par le premier argument de l'appel système (donc de l'ordre de migration). E317. Cette étape consiste à allouer une nouvelle pile utilisateur, dans le nouveau contexte précédemment activé à l'étape E316, et à l'initialiser. Cette initialisation consiste à empiler les paramètres de la fonction à appeler, ainsi que le pointeur T, qui est l'argument implicite this dans le modèle objet du C++. Cette étape permet aussi de justifier la seconde étape car les paramètres empilés se trouvent initialement dans l'ancienne pile utilisateur. Or, le contexte dans lequel ils étaient stockés n'est plus accessible (le nouveau contexte est actif), Par conséquent, pour récupérer ces paramètres, il est nécessaire de les avoir au préalable copiés localement dans la mémoire superviseur. E318. Pour terminer cet appel système et exécuter la fonction utilisateur dans le mode de privilège utilisateur, il faut préparer la pile système en empilant au moins l'adresse de la pile utilisateur, ainsi que l'adresse de code à exécuter. Ce dernier argument correspond au second argument de l'ordre de migration. E319. Une fois la pile système initialisée, il ne reste plus qu'à utiliser une instruction processeur pour basculer vers le niveau de priorité utilisateur, ce qui aura pour conséquence de finir l'appel système et donc d'exécuter le code dans le nouveau contexte. La figure 14 représente un algorithme utilisé pour revenir au contexte initial dans le cas d'une migration avec retour selon l'invention. Il comporte les sous-étapes E321 à E325 qui vont maintenant être décrites. E321. A la fin de l'exécution de la portion de code englobée par la migration avec retour (voir figure 8), ou alors au moment de l'exécution de l'instruction switch back (voir figure 7), un appel système est fait. E322. La pile utilisateur est alors libérée, car elle ne servira plus par la suite. E323. L'ancien contexte est restauré. La référence de cet ancien contexte vient de l'étape E314 de l'algorithme précédent (figure 13). E324. La pile système est préparée pour le retour vers le mode utilisateur, comme à l'étape E318 de l'ancien algorithme. Les deux arguments important de cette préparation sont l'adresse de la nouvelle pile utilisateur ainsi que l'adresse du code à exécuter, arguments qui ont été stockés à l'étape E314 de l'algorithme précédent. E325. Finalement, comme à l'étape E319 de l'algorithme précédent, l'appel système est terminé pour exécuter le code utilisateur. Le procédé de traduction du code source muti-contexte, tel qu'exposé ci-dessus, peut être réalisé par application d'un programme exécutable au code source, cet exécutable créant un code produit à partir du code source initial, en suivant les étapes du procédé exposé ci-dessus. Il est clair que cette transformation peut avantageusement être intégrée à un compilateur par exemple de type C pour créer un compilateur adapté à prendre en compte une logique multi-contexte telle qu'exprimée avec le langage de programmation à instruction spécifique défini plus haut. Une fois que le code source comprenant une sémantique avec migration de fils d'exécution a été écrit par un programmeur, ce code est donc traduit par le procédé selon l'invention en un code produit, destiné à être compilé de façon classique avec un compilateur par exemple de type C, puis à être exécuté sur un système informatique utilisant un système d'exploitation Chorus. Dans ce cas, les applications ainsi développées utilisent effectivement la migration de fils d'exécution entre différents contextes, conformément à ce qui a été exposé plus haut. Bien entendu, la présente invention ne se limite pas aux détails des formes de réalisation décrits ici à titre d'exemple, mais s'étend au contraire aux modifications à la portée de l'homme de l'art, sans sortir du cadre de l'invention. REVENDICATIONS 1. Procédé de traduction d'un code source (1) vers un code produit, lesdits codes étant écrits dans un langage informatique permettant de décrire au moins une tâche (A ()), à laquelle sont associés une première méthode, un premier contexte mémoire (A) et un code informatique, ledit code produit pouvant être exécuté dans un environnement multi-tâches avec gestion de mémoire virtuelle, ledit procédé étant caractérisé en ce que il comporte une étape de migration (E31) comportant les sous-étapes suivantes : - recherche dans ledit code source d'une instruction (switch to) et de ses paramètres, ladite instruction (switch to) représentant un ordre de migration du premier contexte (A), vers un nouveau contexte (B) associé à une tâche cible (B ()), pour l'exécution d'une partie (3) de ladite première méthode de ladite tâche (A ()) ; et - transformation du code source (1) en code produit fonctionnellement équivalent, tel que ladite partie (3) soit exécutable au sein du nouveau contexte (B). 2. Procédé de traduction selon la revendication 1, caractérisé en ce que, dans le cas où ladite partie (3) est une instruction composée, ladite étape de migration (E31) est suivie par une étape de préparation de migration retour (E32), qui fait suivre ledit ordre de migration (4) par un ordre de migration retour dans ledit premier contexte (A), ledit ordre de migration retour étant représenté dans ledit langage informatique par une deuxième instruction (switch back). 3. Procédé de traduction selon l'une des revendications 1 ou 2, caractérisé en ce que, ladite première méthode de la tâche (A ()) comportant une première partie (2) de déclaration et de code informatique, ladite instruction (switch to) et une seconde partie (3) de code informatique, ladite étape de transformation du code source (1) comporte les étapes suivantes : - conservation, dans ladite première méthode de la tâche (Ao), de ladite première partie (2) de déclaration et de code informatique ; -ajout, dans ladite première méthode, après ladite première partie (2), d'un ordre de migration système (5), ledit ordre de migration système comportant au moins un paramètre ; et - création d'une nouvelle méthode (6) dans ledit nouveau contexte (B) de la tâche cible (BQ), ladite nouvelle méthode (6) ne contenant qu'un code informatique (7) correspondant à ladite seconde partie (3) de ladite première méthode. 4. Procédé de traduction selon la revendication 3, caractérisé en ce que ledit ordre de migration système (5) est un appel de procédure à distance vers ladite nouvelle méthode (6), dans le nouveau contexte (B) de ladite tâche cible (B ()). 5. Procédé de traduction selon l'une des revendications 3 ou 4, caractérisé en ce que ledit ordre de migration système comporte en outre des paramètres correspondants à des variables (8) transférées au cours de la migration du premier contexte (A) vers le nouveau contexte (B). 6. Procédé de traduction selon l'une des revendications 3 à 5, caractérisé en ce que, dans le cas d'un système informatique utilisant un mode superviseur, auquel est associé une pile superviseur, l'ordre de migration système (5) comprend des étapes suivantes : -appel système (E311) pour passer dans ledit mode superviseur ; - première copie (E312) d'au moins un paramètre de l'ordre de migration système (5) dans ladite pile superviseur ; - activation (E316) du nouveau contexte (B) ; -allocation (E317) d'une nouvelle pile utilisateur, dans le nouveau contexte (B), et copie, le cas échéant, des paramètres de ladite nouvelle méthode dans ladite nouvelle pile utilisateur ; - préparation de ladite pile superviseur en copiant une adresse de ladite nouvelle pile utilisateur et l'adresse de ladite seconde partie (3) de code informatique ; et - fin de l'appel système et exécution (E318) de la seconde partie (3) de code informatique dans ledit nouveau contexte (B). 7. Procédé de traduction selon la revendication 6, caractérisé en ce que, dans le cas où ladite seconde partie (3) est une instruction composée, l'ordre de migration système (5) comprend, à l'issue de ladite étape de première copie, une étape de deuxième copie dudit premier contexte (A) et d'une adresse de retour dans ledit premier contexte (A). 8. Procédé de traduction selon l'une quelconque des revendications 1 à 7, caractérisé en ce qu'il comporte en outre, une étape de substitution (E21) qui remplace chaque début et fin d'utilisation d'un espace d'adressage mémoire spécifique à une instanciation d'une tâche langage (A ()) par un sous-programme, ledit sous-programme étant adapté, d'une part, à créer une nouvelle tâche système et, d'autre part, à associer ladite instanciation de la tâche langage avec ladite nouvelle tâche système. 9. Procédé de traduction selon la revendication 8, caractérisé en ce que ladite étape de transformation (E21) remplace une ligne de code Task tA A () dans le programme source par un sous-programme mettant en oeuvre les étapes suivantes : - demande de création d'une tâche système au système d'exploitation ; - allocation d'une portion de mémoire de la taille dudit espace d'adressage mémoire de la tâche langage A () et mappage dans ladite tâche système ; et - association de ladite tâche langage AO avec ladite mémoire mappée. 10. Procédé de traduction selon l'une quelconque des revendications 1 à 9, caractérisé en ce qu'il comporte en outre une étape de mappage (E22), permettant de mapper une tâche BO de type tB sur un tâche AO de type tA, ladite étape de mappage étant associée à un mot clé maps dudit langage et comportant les étapes suivantes : - demande de création d'une tâche système au système d'exploitation ; -allocation d'une portion de mémoire de la taille dudit espace d'adressage mémoire de la tâche A() et mappage dans ladite tâche système ; - mappage de la mémoire associée à la tâche AO dans la tâche BO ; et - association de l'espace d'adressage mémoire de la tâche AO avec ladite mémoire mappée. 11. Procédé de traduction selon la revendication 10, caractérisé en ce que ladite étape de mappage (E22) est réalisée avant ladite étape de migration (E31). 12. Procédé de traduction selon l'une quelconque des revendications 1 à 11 caractérisé en ce qu'il comporte un mécanisme de gestion de privilège, permettant à une tâche AO de s'exécuter en mode privilégié, ledit mécanisme de gestion de privilège étant associé au mot-clef priviledge Kernel et comportant les étapes suivantes : - demande de création d'un tâche de privilège superviseur au système d'exploitation ; - allocation d'une portion de mémoire de la taille dudit espace d'adressage mémoire de la tâche AO et mappage dans ladite tâche système ; et - association de l'espace d'adressage mémoire de la tâche AD avec ladite mémoire mappée. 13. Procédé de traduction selon l'une quelconque des revendications 1 à 12, caractérisé en ce qu'il comporte également une étape de vérification de l'intégrité dudit code source. 14. Dispositif de traduction d'un code source (1) vers un code produit, lesdits codes étant écrits dans un langage informatique permettant de décrire au moins une tâche (Ao), à laquelle sont associés une première méthode, un premier contexte mémoire (A) et un code informatique, ledit code produit pouvant être exécuté dans un environnement multi-tâches avec gestion de mémoire virtuelle, ledit dispositif étant caractérisé en ce qu'il comporte : - des moyens de recherche dans ledit code source d'une instruction (switch to) et de ses paramètres, ladite instruction (switch to) représentant un ordre de migration du premier contexte (A), vers un nouveau contexte (B) associé à une tâche cible (B ()), pour l'exécution d'une partie (3) de ladite première méthode de ladite tâche (A ()) ; et -des moyens de transformation du code source (1) en code produit fonctionnellement équivalent, tel que ladite partie (3) soit exécutable au sein du nouveau contexte (B). 15. Dispositif de traduction selon la revendication 14, caractérisé en ce que lesdits moyens de recherche sont adaptés à rechercher un ordre de migration retour dans ledit premier contexte (A), ledit ordre de migration retour étant représenté dans ledit langage informatique par une deuxième instruction (switch back). 16. Dispositif de traduction, caractérisé en ce qu'il comporte des moyens adaptés à mettre un oeuvre un procédé de traduction selon l'une quelconque des revendications 1 à 13. 17. Compilateur, caractérisé en ce qu'il comporte un dispositif de traduction selon l'une quelconque des revendications 14 à 16. 18. Moyen de stockage d'informations, éventuellement totalement ou partiellement amovible, lisible par un ordinateur ou un processeur, caractérisé en ce qu'il contient des instructions d'un programme d'ordinateur, permettant la mise en oeuvre d'un procédé de traduction selon l'une quelconque des revendications 1 à 13. 19. Programme d'ordinateur chargeable dans un appareil programmable, caractérisé en ce qu'il comporte des séquences d'instructions ou des portions de code logiciel pour mettre en oeuvre les étapes d'un procédé de traduction selon l'une quelconque des revendications 1 à 13, lorsque ce programme d'ordinateur est exécuté sur un appareil programmable.