2017-07-19 1 views
-2

Lorsque Linux charge des bibliothèques partagées, je crois savoir que la section de texte n'est chargée qu'une seule fois dans la mémoire physique et est ensuite mappée sur des tables de pages de différents processus qui la référencent. Où/qui assure/vérifie-t-il que la même section de texte de bibliothèque partagée n'a pas été chargée plusieurs fois dans une mémoire physique?Comment plusieurs copies de la section de texte de la bibliothèque partagée sont-elles évitées dans la mémoire physique?

La duplication est-elle évitée par le chargeur ou par l'appel système mmap() ou existe-t-il un autre moyen et comment?

Edit1: Je dois avoir montré ce qui a été fait jusqu'à présent (recherche). Ici, il est ...

Essayé de tracer une commande de sommeil simple.

$ strace sleep 100 & 
[1] 22824 
$ execve("/bin/sleep", ["sleep", "100"], [/* 26 vars */]) = 0 
brk(0)         = 0x89bd000 
access("/etc/ld.so.preload", R_OK)  = -1 ENOENT (No such file or directory) 
open("/etc/ld.so.cache", O_RDONLY)  = 3 
fstat64(3, {st_mode=S_IFREG|0644, st_size=92360, ...}) = 0 
mmap2(NULL, 92360, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f56000 
close(3)        = 0 
open("/lib/libc.so.6", O_RDONLY)  = 3 
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\0`G\0004\0\0\0"..., 512) = 512 
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f55000 
fstat64(3, {st_mode=S_IFREG|0755, st_size=1706232, ...}) = 0 
mmap2(0x460000, 1426884, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x460000 
mmap2(0x5b7000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x156) = 0x5b7000 
mmap2(0x5ba000, 9668, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x5ba000 
close(3)        = 0 
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f54000 
... 
munmap(0xb7f56000, 92360)    = 0 
... 

Puis vérifié le fichier/proc/pid/maps pour ce processus;

$ cat /proc/22824/maps 
00441000-0045c000 r-xp 00000000 fd:00 2622360 /lib/ld-2.5.so 
... 
00460000-005b7000 r-xp 00000000 fd:00 2622361 /lib/libc-2.5.so 
... 
00e3e000-00e3f000 r-xp 00e3e000 00:00 0   [vdso] 
08048000-0807c000 r-xp 00000000 fd:00 5681559 /usr/bin/strace 
... 

Ici on a vu que l'argument addr pour mmap2() de libc.so.6 avec PROT_READ|PROT_EXEC était à une adresse spécifique. Cela m'amène à croire que le mappage de la bibliothèque partagée dans la mémoire physique était en quelque sorte géré par le chargeur.

+0

Le noyau Linux ainsi que tous les systèmes pertinents liés à cette question sont open-source, avec la source disponible pour la recherche. –

+0

@Someprogrammerdude C'est vrai, mais tout le monde capable de vérifier cela dans le noyau, l'a appris il y a longtemps, alors que tout le monde peut être curieux, comment cela fonctionne-t-il? – peterh

Répondre

0

Les bibliothèques partagées sont chargées par le syscall mmap(), et le noyau Linux est intelligent. Il dispose d'une structure de données interne qui mappe les descripteurs de fichier (contenant l'instance de montage et le numéro d'inode) sur les pages mappées. L'éditeur de liens dynamiques (son code est quelque part /lib/ld-linux.so ou similaire) utilise uniquement cet appel mmap() pour mapper les bibliothèques (puis déplace leurs tables de symboles), cette déduplication au niveau de la page est entièrement effectuée par le noyau.

Les mappings se produisent avec les indicateurs PROT_READ|PROT_EXEC|PROT_SHARED, ce que vous pouvez vérifier facilement en plaçant n'importe quel outil (comme strace /bin/echo).

+0

la référence aux descripteurs de fichiers et le numéro d'inode était ce que je cherchais. merci – emilk

+0

Mon plaisir :-) Si une réponse a résolu votre problème, vous pouvez l'accepter en cliquant sur l'icône de la pipe sur la gauche. C'est une récompense pour le répondant, et aussi pour les futurs visiteurs, que le problème est déjà résolu. – peterh