2.10. Édition de liens de 5 modules

On dispose de 5 modules compilés, mémorisés dans les fichiers cmpdisk.o, cmpfile.o, disk_io.o, lsbrk.o, printstr.o. Ces 5 modules constituent la base d'un programme, qui nécessite en plus des modules de bibliothèque.
On dispose d'un premier outil, appelé listliens, qui imprime les liens des modules, en indiquant leur type ainsi que éventuellement leur valeur. Le résultat de l'application de cet outil sur les 5 modules est donné en table 1, où las signifie lien à satisfaire et lu lien utilisable.
On dispose également d'un second outil, appelé taille, qui donne la taille d'un module objet, c'est-à-dire le nombre d'emplacements occupés par ce module. Le résultat de l'application de cet outil sur les 5 modules est donné en table 2.
On se propose de faire l'édition des liens des 5 modules dans l'ordre suivant :
cmpdisk.o, cmpfile.o, disk_io.o, lsbrk.o, printstr.o.
A- Quel est la place et le rôle de l'éditeur de liens dans la chaîne de production de programmes.
B- En supposant que l'éditeur de liens suit l'algorithme présenté dans le livre, définir les adresses d'implantations des modules, en justifiant votre réponse.
C- Donner le contenu de la table des liens après prise en compte des liens des 5 modules (premier passage). Expliquez votre raisonnement.

cmpdisk.o:
las
bloc_transfer_dr


las
close_printer


las
compare_file


lu
compare_hierarch
1862

las
exit


lu
exit_prog
2820

lu
file_error
422

las
free


las
get_memory


lu
main
2460

las
open_drive


las
open_printer


las
print_string

cmpfile.o:
las
bloc_transfer_dr


lu
compare_file
200

las
file_error

disk_io.o:
lu
bloc_transfer_dr
2118

las
exit


las
exit_prog


las
get_memory


lu
open_drive
236

las
print_string

lsbrk.o:
las
exit_prog


lu
get_memory
0

las
lmalloc


las
print_string

printstr.o:
lu
ask_confirm
758

lu
close_printer
1028

las
getchar


lu
open_printer
996

lu
print_string
340

las
write

table 1. résultat de "listliens"

cmpdisk.o
3376


cmpfile.o
644


disk_io.o
3862


lsbrk.o
82


printstr.o
1196


table 2. résultat de "taille"

D- Donner la liste des références croisées en expliquant votre raisonnement.
E- Certains liens ne sont pas définis. Donner lesquels. Comment seront-ils satisfaits?
F- Indiquer les liens qui ne sont à satisfaire dans aucun module. Sachant que le module du fichier cmpdisk.o est le programme principal dont l'adresse de lancement est main, et que les autres modules sont des sous programmes de service pouvant être utilisés dans d'autres programmes, précisez pour chacun d'eux s'il vous paraît logique de les trouver en tant que lien utilisable.
G- Dans quel ordre faudrait-il mettre les modules dans une bibliothèque, sachant que l'éditeur de lien la parcourt séquentiellement.
H- En vous inspirant de la question F, voyez-vous une utilisation particulière de l'outil listliens?
Solution de l'exercice 2.10

2.10.1. Question A

La construction de programmes peut devenir relativement complexe lorsque la taille du programme devient importante. Pour cela, on est amené à découper les programmes en modules. Chacun des modules peut être compilé de façon séparée. L'éditeur de liens a pour but de constituer un programme exécutable à partir d'un ensemble de modules. Le chargeur peut ensuite mettre en mémoire ce programme exécutable pour l'exécuter.
Le rôle de l'éditeur de liens se présente sous plusieurs aspects :
  1. Assurer une fonction de placement des modules dans le programme exécutable. Ces modules ont été compilés de façon à pouvoir s'exécuter à un certain emplacement mémoire. Il s'agit de faire en sorte que tous les modules occupent des espaces disjoints à l'exécution (sauf si on désire utiliser des techniques de recouvrement qui ne seront pas abordées ici). La méthode la plus simple consistera à les mettre les uns derrière les autres en tenant compte de leur taille.
  2. Translater les modules de façon à permettre leur bon fonctionnement dans l'espace qui leur a été attribué.
  3. Relier les modules entre eux. Si l'on désire faire un programme avec un ensemble de modules, c'est que ces modules doivent coopérer pour cette exécution. Ceci veut dire que des sous programmes ou des variables appartenant à un module doivent pouvoir être utilisé par un autre module. Pour cela on a introduit la notion de lien représentant un tel depuis un module vers un autre. La partie du lien qui se trouve dans le module qui cherche à accéder à l'objet s'appelle le lien à satisfaire et la partie du lien qui est situé dans le module qui fourni l'objet s'appelle le lien utilisable. Relier consiste à associer les liens à satisfaire aux liens utilisables correspondants.
  4. Compléter la liste des modules avec des modules en bibliothèque. Une liste initiale de modules est fournie à l'éditeur de liens qui relie les liens à satisfaire aux liens utilisables correspondants. Il est possible que certains liens à satisfaire ne correspondent à aucun lien utilisable d'un module de la liste. L'éditeur de liens utilisent ces liens à satisfaire pour rechercher dans les bibliothèques de modules s'il peut en trouver un qui contienne ce lien comme lien utilisable. Lorsqu'il en trouve, il ajoute ce module à la liste.

2.10.2. Question B

En faisant l'édition de liens des 5 modules dans l'ordre indiqué, les modules seront placés dans le programme exécutable dans cet ordre, les uns derrière les autres, en commençant à 0 pour le premier.

cmpdisk.o
0


cmpfile.o
3376


disk_io.o
4020


lsbrk.o
7882


printstr.o
7964


carte d'implantation des modules

Les modules de bibliothèques éventuels seront mis après, c'est-à-dire commenceront en 9160.

2.10.3. Question C.

Au cours du premier passage, l'éditeur de lien fixe la carte d'implantation des modules comme indiqué dans la question précédente. En même temps, il prend en compte l'ensemble des liens de ces modules, pour les mettre dans la table des liens. Pour chacun des liens trouvés dans un module, on effectue le traitement suivant :
  1. S'il s'agit d'un lien utilisable, on modifie sa valeur en lui ajoutant l'adresse de début d'implantation du module, et on le recherche dans la table.
  1. S'il s'agit d'un lien à satisfaire, on le recherche dans la table.

Appliquons ce traitement aux liens des modules fournis. Les liens du premier module sont entrés dans la table, soit comme lien à satisfaire, soit comme lien utilisable avec sa valeur (à laquelle on ajoute 0).
las
bloc_transfer_dr

las
close_printer

las
compare_file

lu
compare_hierarch
1862
las
exit

lu
exit_prog
2820
lu
file_error
422
las
free

las
get_memory

lu
main
2460
las
open_drive

las
open_printer

las
print_string

Le deuxième module conduit simplement à la modification du lien compare_file, qui devient utilisable, avec la valeur 3376+200=3576. Le troisième module, quant à lui, conduit à la transformation en liens utilisables d'une part de bloc_transfer_dr dont la valeur est maintenant 4020+2118=6138 et d'autre part de open_drive dont la valeur est maintenant 4020+236=4256.
las
bloc_transfer_dr
6138
las
close_printer

las
compare_file
3576
lu
compare_hierarch
1862
las
exit

lu
exit_prog
2820
lu
file_error
422
las
free

las
get_memory

lu
main
2460
las
open_drive
4256
las
open_printer

las
print_string

Le quatrième module transforme le lien get_memory en lien utilisable, avec la valeur 7882+0=7882, et ajoute le lien lmalloc comme lien à satisfaire.
las
bloc_transfer_dr
6138
las
close_printer

las
compare_file
3576
lu
compare_hierarch
1862
las
exit

lu
exit_prog
2820
lu
file_error
422
las
free

las
get_memory
7882
lu
main
2460
las
open_drive
4256
las
open_printer

las
print_string

las
lmalloc


Enfin, le cinquième module conduit à la transformation en liens utilisables de close_printer avec la valeur 7964+1028=8992, open_printer avec la valeur 7964+996=8960 et print_string avec la valeur 7964+340=8304. De plus, sont ajoutés à la table le lien ask_confirm comme lien utilisable avec la valeur 7964+758= 8722, et les liens get_char et write comme liens à satisfaire.
las
bloc_transfer_dr
6138
las
close_printer
8992
las
compare_file
3576
lu
compare_hierarch
1862
las
exit

lu
exit_prog
2820
lu
file_error
422
las
free

las
get_memory
7882
lu
main
2460
las
open_drive
4256
las
open_printer
8960
las
print_string
8304
las
lmalloc

lu
ask_confirm
8722
las
getchar

las
write

2.10.4. Question D.

La liste des références croisées est obtenue en indiquant pour chaque lien, le module dans lequel il est défini en tant que lien utilisable (normalement il y en a au plus un), et la liste des modules dans lequel il apparaît en tant que lien à satisfaire.
lien
utilisable
à satisfaire
bloc_transfer_dr
disk_io.o
cmpdisk.o, cmpfile.o
close_printer
printstr.o
cmpdisk.o
compare_file
cmpfile.o
cmpdisk.o
compare_hierarch
cmpdisk.o

exit

cmpdisk.o, disk_io.o
exit_prog
cmpdisk.o
disk_io.o, lsbrk.o
file_error
cmpdisk.o
cmpfile.o
free

cmpdisk.o
get_memory
lsbrk.o
cmpdisk.o, disk_io.o
main
cmpdisk.o

open_drive
disk_io.o
cmpdisk.o
open_printer
printstr.o
cmpdisk.o
print_string
printstr.o
cmpdisk.o, disk_io.o, lsbrk.o
lmalloc

lsbrk.o
ask_confirm
printstr.o

getchar

printstr.o
write

printstr.o

2.10.5. Question E.

Les liens qui restent à satisfaire dans la table des liens après traitement des 5 modules ne sont pas définis, puisqu'ils n'ont pas été trouvés utilisables dans l'un de ces modules. Il s'agit de exit, free, lmalloc, getchar et write. Ces liens devront être satisfaits au moyen de modules de bibliothèques. De fait, il s'agit de procédures courantes, qui font appel au système :
exit permet de terminer l'exécution du programme,
free et lmalloc servent à la gestion dynamique de la mémoire,
getchar et write sont des procédures d'entrées sorties.
L'éditeur de liens recherchera les modules de bibliothèque qui contiennent comme lien utilisable ces liens restant à satisfaire dans la table.

2.10.6. Question F.

La liste des références croisées de la question D montre que compare_hierarch, main et ask_confirm sont définis comme lien utilisables dans un module, mais ne sont mentionnés comme lien à satisfaire dans aucun.

2.10.7. Question G.

Le tableau des références croisées permet de construire le graphe des liens entre les modules. On trace un arc d'un module A vers un module B, s'il y a un lien à satisfaire dans A qui est utilisable dans B. Notons que dans ce cas, le module A devrait être placé avant le module B en bibliothèque pour que l'éditeur de liens ajoute B s'il a déjà ajouté A.

On peut constater sur le graphe ainsi obtenu qu'il y a plusieurs cycles. Ainsi le module cmpdisk.o doit être placé avant le module cmpfile.o, à cause du lien compare_file, mais ce module cmpfile.o doit être placé avant cmpdisk.o à cause du lien file_error. Cependant, le module cmpdisk.o est un programme principal; il ne devrait donc pas faire l'objet d'un chargement automatique, mais être le module de départ qui entraîne le chargement des autres. Il doit donc être mis en premier. Le reste du graphe impose alors la séquence complète, qui est donc : cmpdisk.o, cmpfile.o, disk_io.o, lsbrk.o, printstr.o.

2.10.8. Question H.

Lors de la question F, nous avons pu constater que notre programme principal exportait sans doute inutilement le lien compare_hierarch. L'outil listliens en listant les liens utilisables et les liens à satisfaire permet au programmeur de vérifier qu'un module exporte (liens utilisables) et importe (liens à satisfaire) juste ce qui doit l'être.