Comment sbrk / brk est-il implémenté sous Linux?

Je pensais à la façon dont le kernel Linux implémente les appels système et je me demandais si quelqu’un pouvait me donner une vue d’ensemble du fonctionnement de sbrk / brk?

J’ai examiné le code du kernel, mais il y en a tellement et je ne le comprends pas. J’espérais un résumé de quelqu’un?

    Dans une vue de très haut niveau, le kernel Linux suit la mémoire visible par un processus sous la forme de plusieurs “zones de mémoire” ( struct vm_area_struct ). Il y a aussi une structure qui représente (encore une fois dans une vue de très haut niveau) tout l’espace d’adressage d’un processus ( struct mm_struct ). Chaque processus (à l’exception de certains threads du kernel) a exactement une struct mm_struct , qui à son tour pointe vers toute la struct vm_area_struct pour la mémoire à laquelle elle peut accéder.

    L’ sys_brk système sys_brk (trouvé en mm/mmap.c ) ajuste simplement certaines de ces zones de mémoire. ( sbrk est un wrapper glibc autour de brk ). Pour ce faire, il compare l’ancienne valeur de l’adresse brk (trouvée dans struct mm_struct ) et la valeur demandée.

    Il serait plus simple d’examiner d’abord la famille de fonctions mmap , car brk est un cas particulier.

    vous devez comprendre comment fonctionne la mémoire virtuelle et comment un mappage de MMU est lié à la RAM réelle.

    la vraie RAM est divisée en pages, traditionnellement de 4 Ko chacune. Chaque processus a son propre mapping MMU, qui présente à ce processus un espace mémoire linéaire (4 Go en Linux 32 bits). bien sûr, tous ne sont pas réellement alloués. au début, il est presque vide, c’est-à-dire qu’aucune page réelle n’est associée à la plupart des adresses.

    Lorsque le processus rencontre une adresse non allouée (que ce soit en essayant de le lire, de l’écrire ou de l’exécuter), la MMU génère une erreur (similaire à une interruption) et le système de machine virtuelle est appelé. S’il décide qu’une certaine quantité de RAM doit être présente, il sélectionne une page RAM non utilisée et l’associe à cette plage d’adresses.

    De cette façon, le kernel ne se soucie pas de la manière dont le processus utilise la mémoire, et le processus ne se soucie pas vraiment de la quantité de mémoire vive, il aura toujours le même espace linéaire de 4 Go.

    maintenant, le brk/sbrk fonctionne à un niveau légèrement supérieur: en principe, toute adresse mémoire «au-delà» de cette marque est invalide et ne permet pas d’obtenir une page RAM si elle est accédée. La bibliothèque de l’espace utilisateur gère les allocations de mémoire dans cette limite, et seulement lorsque cela est nécessaire, demande au kernel de l’augmenter.

    Mais même si un processus démarrait en définissant brk au maximum autorisé, les pages RAM réelles ne seraient pas allouées tant qu’il ne commencerait pas à accéder à toutes les adresses mémoire.

    Eh bien, dans une perspective de très haut niveau, le kernel alloue un bloc de mémoire paginable, modifie les tables de pages du processus demandant ce bloc afin que la mémoire soit mappée dans l’espace VA du processus, puis renvoie l’adresse.

    Un concept clé de la manière dont le kernel Linux transmet de la mémoire à un processus utilisateur est que le segment de processus disponible (le segment de données) grandit à partir du bas. le kernel ne garde pas trace de morceaux individuels de mémoire, mais seulement d’un bloc de mémoire continu. Les appels système brk / sbrk augmentent la quantité de mémoire dont dispose le processus, mais cela dépend du processus pour le gérer en pièces utilisables.

    Une conséquence clé de ceci est que la mémoire éparpillée dans l’espace d’adressage des processus qui n’est pas utilisé ne peut pas être renvoyée au système d’exploitation pour d’autres utilisations. Seule la mémoire à la toute fin du segment de données peut être renvoyée au système d’exploitation, de sorte que la mémoire en cours d’utilisation près de la fin devrait être déplacée vers le haut. En pratique, presque aucun allocateur ne le fait. Pour cette raison, il est généralement important de bien gérer la quantité maximale de mémoire utilisée par un processus, car cela détermine la quantité de mémoire restante pour les autres processus.