2015-09-23 2 views
0

Lire du livre que, lorsqu'un processus est lancé, son espace d'adressage du processus privé est crééComment "l'espace d'adressage du processus Linux" est-il stocké?

Disons qu'il est de 0x0 à 0xMAX

Et une partie de l'espace est le tas, et nous avons écrit un pour que la boucle coïncide avec malloc (date 1k) jusqu'à ce qu'elle retourne false. Il a alloué 3 Go de date. Donc, question, si 0x0 à 0xMAX est alloué au début, cela signifie que 0x0 à 0xMAX est plus grand que 3GB (puisqu'il y a pile, contrôle ...) depuis le début?

Si un processus peut prendre plus de 3 Go au début, il faut que je comprenne mal.

Quelqu'un peut-il expliquer comment ce 0x0 - 0xMAX est stocké dans le begging?

+1

no. l'exécution d'un processus n'alloue pas par magie l'intégralité de l'espace mémoire possible pour l'application. le compilateur peut calculer combien de mémoire est nécessaire pour stocker le code et les données statiques, et cette mémoire sera allouée au démarrage du processus. –

+0

@MarcB Comme mon processus, il peut prendre en argument pour créer un tas de 3 ou 3 Mo que la compilation peut difficilement connaître. Donc, dans ce cas, le système d'exploitation va-t-il mettre à jour dynamiquement tout l'espace mémoire? comme tas est de 0xXX continuer à 0xMax, et la pile est de 0xMax jusqu'à la baisse. Si le système d'exploitation veut le mettre à jour dynamiquement, tout l'espace sera mis à jour. – thundium

+0

@marcb, Probablement un peu tangentiel mais il y a une copie en écriture du processus parent quand un fork se produit. –

Répondre

1

Normalement, le chargement d'un exécutable dans la mémoire est piloté par le chargeur linux ld. Par exemple, si je crée un programme C très simple permet de dire:

void main {} 

Après avoir compilé ce programme avec gcc, nous obtenons un fichier exécutable (format ELF) a.out. Si nous analysons les dépendances de ce programme très simple ont en exécutant ldd nous trouvons:

linux-gate.so.1 => (0x00545000) 
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00ccb000) 
/lib/ld-linux.so.2 (0x00594000) 

Le premier linux-gate.so est exposé par le noyau pour faire des appels système. ld-linux.so est en fait le chargeur linux. C'est le responsable de charger n'importe quel exécutable dans la mémoire et l'exécuter. Si nous jetons un coup d'oeil à notre a.out généré (en utilisant l'outil hexedit par exemple), nous pouvons voir qu'il est en-tête contient une référence à l'endroit où la ld-linux est situé:

.ELF........................4...8....... 
4. ...(.........4...4...4... ... ....... 
........T...T...T....................... 
........................................ 
........................(...(...(....... 
................h...h...h...D...D....... 
....P.td............4...4...........Q.td 
............................R.td........ 
..................../lib/ld-linux.so.2.. 
............GNU......................... 
....GNU....F*QLk$,.....)..Yl............ 

Une fois que vous démarrez le processus, le Le chargeur ld-linux vérifie d'abord quelles sont les bibliothèques partagées dont vous avez besoin (dépendent) et si elles sont disponibles ou non. Dans le cas où vous dépendez d'une bibliothèque partagée qui n'est pas disponible, ld-linux ne chargera pas le processus (ld-linux regarde dans votre variable d'environnement LD_LIBRARY_PATH, dans le fichier /etc/ld.so.cache et enfin dans les chemins par défaut:/lib et/usr/lib (man ld-linux pour plus d'informations)

Une fois que le ld-linux vérifie que toutes les bibliothèques sont là, il alloue la mémoire pour charger le processus Normalement un exécutable a plusieurs segments, pour plus de simplicité peut les réduire en texte (code), bss (données non initialisées), données (données initialisées et statiques) Lorsque le processus est chargé en mémoire, le chargeur réserve la quantité de mémoire nécessaire pour contenir toutes ces sections, et le mapper dans l'espace virtuel de le processus toutes les bibliothèques partagées dont le processus dépend.Vous pouvez voir la liste des cartes d'un certain processus linux en consultant:

cat /proc/pid_of_process/maps 

Si je lance une version modifiée du programme simple ci-dessus (en ajoutant un appel à un usleep afin d'obtenir le processus pid) et vérifier ses cartes, nous obtenons les éléments suivants (le _ sont juste pour cacher le vrai chemin où ma maison apparaît):

003a5000-003a6000 r-xp 00000000 00:00 0   [vdso] 
0075a000-008fd000 r-xp 00000000 08:03 2137894 /lib/i386-linux-gnu/libc-2.15.so 
008fd000-008ff000 r--p 001a3000 08:03 2137894 /lib/i386-linux-gnu/libc-2.15.so 
008ff000-00900000 rw-p 001a5000 08:03 2137894 /lib/i386-linux-gnu/libc-2.15.so 
00900000-00903000 rw-p 00000000 00:00 0 
00e4a000-00e6a000 r-xp 00000000 08:03 2137906 /lib/i386-linux-gnu/ld-2.15.so 
00e6a000-00e6b000 r--p 0001f000 08:03 2137906 /lib/i386-linux-gnu/ld-2.15.so 
00e6b000-00e6c000 rw-p 00020000 08:03 2137906 /lib/i386-linux-gnu/ld-2.15.so 
08048000-08049000 r-xp 00000000 08:05 3589145 /______________/test/a.out 
08049000-0804a000 r--p 00000000 08:05 3589145 /______________/test/a.out 
0804a000-0804b000 rw-p 00001000 08:05 3589145 /______________/test/a.out 
b771f000-b7720000 rw-p 00000000 00:00 0 
b7745000-b7747000 rw-p 00000000 00:00 0 
bf884000-bf8a5000 rw-p 00000000 00:00 0   [stack] 

Ceci est en fait la carte de mémoire virtuelle du processus. Ces pages sont mappées à la mémoire physique et chaque processus a son propre PMT (table de carte de programme) qui est utilisé pour traduire entre les adresses physiques et virtuelles. En général, une mémoire de processus a la mise en page suivante:

(de http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory/)

enter image description here

Ainsi, avec ces informations à l'esprit et revenir à votre question initiale,

Alors , question, si 0x0 à 0xMAX est alloué au début, cela signifie que 0x0 à 0xMAX est supérieur à 3 Go (puisqu'il y a pile, contrôle ...) depuis le début?

La réponse est qu'il n'y a pas de telle réservation. Le chargeur réserve la mémoire physique nécessaire pour exécuter le processus. Après cela, en fonction des besoins du processus (allocation de mémoire dynamique) et de son comportement, ses zones de tas et de piles peuvent augmenter et diminuer. Chaque fois que le processus doit accéder à de la mémoire (virtuelle) qui n'est pas réellement présente dans la mémoire physique, une erreur de page est émise et cette page est chargée depuis le disque vers l'emplacement réservé dans la mémoire physique. Parfois, pour ce faire, le noyau doit permuter une page qui appartient à un autre processus sur le disque. La mémoire physique est une ressource limitée que le système d'exploitation doit gérer correctement afin de permettre tous les processus en cours. Avec cette stratégie, le noyau Linux peut exécuter plusieurs processus où chacun a normalement une mémoire virtuelle de 4 Go (systèmes 32 bits) dans une mémoire physique mineure que celle-là (spécialement dans le passé). En général, même si vous réservez dynamiquement de la mémoire (à l'aide de malloc, par exemple), l'appel réussit, mais vous ne réservez pas encore cette mémoire physique. Votre processus l'obtiendra une fois qu'il essayera de l'utiliser (en lisant ou en écrivant à cette mémoire).

C'est peut-être une réponse longue. J'espère que je n'ai pas manqué beaucoup de détails et que cela vous aide à comprendre l'anatomie d'une mémoire de processus sous linux.

+0

Merci, j'ai beaucoup appris de ça. –

0

Il y a quelques idées fausses ici. Tout d'abord, il existe une différence entre l'espace de traitement dpace et la mémoire allouée au processus. Deuxièmement, il est peu probable que la plage d'adresses valides dans l'espace adresse soit linéaire. Il est le plus susceptible d'être dans plusieurs zones de mémoire déconnectées. Si vous avez fait malloc dans une boucle, vous étiez en train de provoquer (a) l'ajout de pages valides au processus (b) en provoquant l'allocation de la mémoire supplémentaire en plus de celle retournée par malloc. Troisièmement, au début d'un processus, il existe des tables de pages. (Ignorer le clonage) Ces tableaux ne font référence à rien au début du processus. Votre processus doit faire en sorte que les pages soient attribuées et affectées aux tables.