Copyright © 2000 Alex Vrenios
Copyright © 2000 Dominique Lazure
Article paru dans le n°51 de la Gazette Linux de mars 2000.
Cet article est publié selon les termes de la Open Publication License. La Linux Gazette n'est ni produite, ni sponsorisée, ni avalisée par notre hébergeur principal, SSC, Inc.
Table des matières
La mobilité logicielle peut signifier différentes choses suivant les personnes. Par exemple, l'informatique mobile est souvent assimilée à l'accès au courrier électronique sur un ordinateur portable, la migration de processus se rapporte à la redistribution automatique de la charge d'un réseau de stations, et un agent mobile décrit un processus en cours d'exécution, collectant les données avant de rapatrier un résultat complet sur un site destinataire. Le premier exemple est une extension du modèle client/serveur décrit depuis les années 1980, alors que les autres exemples, illustrant de la migration autonome de processus à travers un réseau de machines, sont des sujets de recherche pointus[1].
Les systèmes en grappes sont des ordinateurs parallèles, réseaux de stations qui présentent au client l'interface d'accès d'un unique serveur. De nombreux processus peuvent s'exécuter sur une grappe, parmi lesquels certains peuvent s'auto-dupliquer afin de répondre à un accroissement soudain du débit de requêtes des clients. Un système d'exploitation de grappes doit pouvoir inciter un ou plusieurs de ces processus à migrer vers d'autres nœuds du réseau, équilibrant ainsi la charge totale de la grappe.
Les agents autonomes sont de simples processus dont la plus efficace des descriptions est l'illustration. Considérons que vous vouliez assembler les composants les moins chers afin de construire votre ordinateur de rêves. Imaginez devoir appeler ou visiter tous les fournisseurs afin de comparer les prix des cartes mères, des disques, et des lecteurs de CD-Roms, etc. Maintenant, imaginez envoyer sur le web un agent logiciel intelligent qui se chargerait d'examiner tous les sites afin d'en rapporter la liste de tous les composants les moins chers, avec prix et URLs. Si vous lui confiez votre numéro de carte bancaire, tous ces composants pourraient arriver directement devant votre porte ! Voici l'idée.
Le tout premier problème à résoudre pour mettre en œuvre le système de migration est de définir la façon dont un processus dupliqué sera lancé à partir d'un processus actif. Ce n'est pas un simple fork distant car le nouveau processus doit pouvoir repartir au début de son exécution. Ce n'est pas un simple rsh car le code exécutable du processus n'existe par forcément sur le nœud distant. Quelles sont les techniques à utiliser ? Quelles sont les modifications à apporter au système de fichiers distant pour permettre la prise en compte d'une requête d'exécution d'une copie du processus actif ? Examinons ces questions qui définissent le clonage de processus.
L'approche consiste à développer un nouveau service et d'y
associer une interface via une fonction. Le processus appèle cette
fonction en précisant le nom de la machine distante. La fonction
effectue la liaison via le démon d'interconnexion inetd
sur un
port prédéterminé de la machine distante afin de déclencher le
service de clonage.
Les vieux systèmes Unix lançaient des démons pour chaque service à
disposition des autres machines. Quand vous utilisiez telnet,
par exemple, un démon dédié au telnet
, nommé telnetd
,
attendait une connexion sur le port 23 de la machine distante. (Le
port 23 est toujours utilisé par telnet
. C'est un des nombreux
ports pré-définis énumérés dans /etc/services
). De par le nombre
croissant de ces démons en attente de connexion, la mémoire virtuelle
disponible et le nombre de processus utilisateurs devinrent
limités.
Le super-démon résolvit ces problèmes en attendant une connexion
sur un quelconque des ports parmi toute une liste pré-définie, et en
lançant automatiquement le serveur associé au service effectivement
accédé. Il suffit maintenant d'ajouter une ligne à deux fichiers pour
enregistrer un nouveau service. Seul le super-utilisateur peux éditer
ces fichiers et ré-initialiser inetd
afin de relire ces
fichiers[2].
Gardez à l'esprit que lorsque vous autorisez un processus d'une machine distante à lancer une copie de lui-même sur votre machine, vous acceptez un risque important que ce nouveau processus soit hostile. Toutes les machines de mon réseau étant sous mon contrôle, je ne suis pas concerné par ce risque. Ce problème ne sera plus discuté par la suite.
Le service doit être déclaré dans /etc/services
. Ajoutez l'entrée
comme suit :
clone 5050/tcp # automatically starts cloned
où clone
est le nom du service,
5050
est le port pré-défini, et tcp
est le
protocole de transport. Nous avons choisi le port 5050 parce-qu'il est
plus grand que le nombre de ports dédiés au système et qu'il était
libre. (La connotation fifty-fifty de 50-50 le rendra plus facilement
mémorisable).
Le service de clônage doit être défini dans /etc/inetd.conf
comme suit :
clone stream tcp nowait root /user/bin/cloned clone
où clone
est le nom du service précisé dans
/etc/services
. (Se reporter aux pages man d'inetd.conf
pour la
description des autres paramètres[2].) Notons que inetd
ne prendra
pas en compte ce nouveau service qu'au prochain reboot, ou lorsque
vous lancerez une commande pour forcer la relecture de ce fichier de
configuration. Pour cela, exécutez en tant que super-utilisateur la commande suivante
killall -HUP inetd
Votre programme fait appel à la fonction clone()
avec le nom de la
machine sur laquelle doit être exécutée la nouvelle copie du
processus. La fonction clone()
détermine le nom du processus actif en
sélectionnant son propre pid
dans le résultat d'une commande
ps. Puis elle détermine le chemin vers l'exécutable avec la
commande which.
Quand clone()
se connecte sur le port 5050, inetd
accepte la
connexion et construit les liaisons nécessaires pour associer l'entrée
standard du processus cloné au flux d'arrivée sur le port et sa sortie
standard sur le flux de sortie. Le processus cloné est lancé à partir
de inetd
via les appels système
fork()
et execl()
[3].
Quand le clone prend la main sur la machine distante, il lit le nom de
l'exécutable qui lui est envoyé en premier. Le code exécutable reçu
ensuite est écrit dans l'espace /tmp
sous le même nom.
L'application locale appelle clone()
avec le nom de la machine
distante. La fonction clone()
se connecte au port du service de
clonage, provoquant le lancement du clone sur la machine
distante. Elle envoie ensuite une copie de l'exécutable vers la
machine distante via le même port. La copie est déposée dans /tmp
par
le démon de clonage puis activée par un fork()
et un execl()
.
Ce qui arrive ensuite est du ressort de l'application. Vous avez la possibilité d'établir une nouvelle connexion avec votre clone distant et de laisser ainsi les deux copies activées. Vous pouvez aussi mettre fin au processus local et effectuer ainsi de la migration d'agent. Vous pouvez même recopier sur une tierce machine une nouvelle version du processus à partir de la copie distante et obtenir ainsi une ribambelle de clones en réseau.
Le comportement final sera déterminé par votre application, mais le premier pas est d'arriver à rendre un processus actif sur une machine distante. Un programme test.c et le démon de clonage, cloned.c ainsi que sa fonction d'interface, clone.c sont inclus dans cet article. Tout est écrit en C et testé avec la distribution Linux RedHat version 4.2.
L'adaptation française de ce document a été réalisée dans le cadre du Projet de traduction de la Gazette Linux.
Vous pourrez lire d'autres articles traduits et en apprendre plus sur ce projet en visitant notre site : http://www.traduc.org/Gazette_Linux.
Si vous souhaitez apporter votre contribution, n'hésitez pas à nous rejoindre, nous serons heureux de vous accueillir.