2009-06-15 4 views
17

Ich habe darüber nachgedacht, wie der Linux-Kernel Systemaufrufe implementiert, und ich fragte mich, ob mir jemand einen Überblick über die Funktionsweise von sbrk/brk geben könnte.Wie wird sbrk/brk in Linux implementiert?

Ich habe den Kernel-Code überprüft, aber es gibt nur so viel davon und ich verstehe es nicht. Ich habe auf eine Zusammenfassung von jemandem gehofft?

Antwort

22

In einer sehr hohen Ansicht verfolgt der Linux-Kernel den Speicher, der für einen Prozess sichtbar ist, als mehrere "Speicherbereiche" (struct vm_area_struct). Es gibt auch eine Struktur, die (wiederum in einer sehr hohen Ansicht) den gesamten Adressraum eines Prozesses repräsentiert (struct mm_struct). Jeder Prozess (außer einigen Kernel-Threads) hat genau einen struct mm_struct, der wiederum auf alle struct vm_area_struct für den Speicher zeigt, auf den er zugreifen kann.

Der Systemaufruf sys_brk (gefunden in mm/mmap.c) passt einfach einige dieser Speicherbereiche an.(sbrk ist ein glibc Wrapper um brk). Dies geschieht durch den Vergleich des alten Wertes der brk Adresse (gefunden innerhalb struct mm_struct) und des angeforderten Wertes.

Es wäre einfacher, zuerst die mmap Familie von Funktionen zu betrachten, da brk ein Sonderfall davon ist.

+0

"(sbrk ist ein Glibc-Wrapper um brk)" - Ich hatte Mühe, zu finden der Systemaufruf für sbrk. Es gibt keinen, macht jetzt Sinn. – automaton

4

Nun, aus der Super-High-Level-Perspektive, der Kernel reserviert einen auslagerbaren Speicherblock, ändert die Seitentabellen des Prozesses fordert diesen Block, so dass der Speicher in den VA-Bereich des Prozesses zugeordnet ist, dann gibt die Adresse zurück.

+0

Also hält der Kernel so ziemlich eine Datenstruktur irgendwo, die sagt "Prozess x besitzt Speicherplatz y"? – samoz

+1

Jeder Prozess hat sein eigenes MMU-Mapping, das (unter anderem) sagt, welche Seiten es besitzt. – Javier

+0

Nicht nur der Kernel - dies wird von der Hardware benötigt und wird jedes Mal im CR3-Register gesetzt, wenn ein Kontextwechsel stattfindet. –

2

Ein Schlüsselkonzept dafür, wie der Linux-Kernel Speicher an einen Benutzerprozess weitergibt, ist, dass der verfügbare Heap (das Datensegment) von unten nach oben wächst. Der Kernel verfolgt nicht einzelne Speicherbereiche, sondern nur einen fortlaufenden Speicherblock. Die Systemaufrufe von brk/sbrk erweitern die Speichermenge, die der Prozess hat, aber es ist Aufgabe des Prozesses, sie in verwendbaren Teilen zu verwalten.

Eine wichtige Konsequenz daraus ist, dass über den Adressraum des Prozesses verstreuter Speicher, der nicht verwendet wird, nicht für andere Zwecke an das Betriebssystem zurückgegeben werden kann. Nur Speicher am Ende des Datensegments kann an das Betriebssystem zurückgegeben werden, so dass der Speicher nahe dem Ende nach unten nach oben verschoben werden müsste. In der Praxis tun dies fast keine Zuordner. Aus diesem Grund ist es in der Regel wichtig, die maximale Speichermenge, die ein Prozess verwendet, zu verwalten, da dies bestimmt, wie viel Speicher für andere Prozesse übrig bleibt.

17

müssen Sie verstehen, wie der virtuelle Speicher funktioniert und wie sich ein MMU-Mapping auf den realen RAM bezieht.

Real-RAM ist in Seiten aufgeteilt, traditionell 4kB jeweils. Jeder Prozess verfügt über ein eigenes MMU-Mapping, das diesem Prozess einen linearen Speicherbereich (4 GB in 32-Bit-Linux) zur Verfügung stellt. natürlich sind nicht alle von ihnen tatsächlich zugeteilt. Zunächst ist es fast leer, dh die meisten Adressen haben keine richtige Seite.

Wenn der Prozess eine nicht zugewiesene Adresse erreicht (entweder versucht, zu lesen, zu schreiben oder auszuführen), generiert die MMU einen Fehler (ähnlich einem Interrupt), und das VM-System wird aufgerufen. Wenn es entscheidet, dass irgendein RAM dort sein sollte, wählt es eine unbenutzte RAM-Seite und assoziiert mit diesem Adressbereich.

so kümmert sich der Kernel nicht, wie der Prozess Speicher verwendet, und der Prozess kümmert sich nicht wirklich, wie viel RAM dort ist, wird es immer die gleichen linearen 4 GB Adressraum haben.

jetzt arbeiten die brk/sbrk auf einer etwas höheren Ebene: im Prinzip jede Speicheradresse 'jenseits' dieser Marke ist ungültig und wird nicht eine RAM-Seite erhalten, wenn zugegriffen wird, würde der Prozess stattdessen getötet werden. Die Userspace-Bibliothek verwaltet Speicherzuordnungen innerhalb dieses Limits und fordert den Kernel nur bei Bedarf auf, diesen zu erhöhen.

Aber auch wenn ein Prozess gestartet wurde, indem brk auf das maximal zulässige gesetzt wurde, würde es keine echten RAM-Seiten zugewiesen bekommen, bis es anfängt, auf all diese Speicheradressen zuzugreifen.

Verwandte Themen