Wenn in Linux der Prozess nach einem (virtuellen) Speicher vom System fragt, wird er nur in vma (Deskriptor des virtuellen Speichers des Prozesses) registriert, aber die physische Seite für jedes virtuelle ist nicht zum Zeitpunkt des Aufrufs reserviert. Später, wenn der Prozess auf diese Seite zugreift, wird ein Fehler auftreten (der Zugriff erzeugt einen Seitenfehler-Interrupt), und der PF # -Handler wird die physische Seite zuweisen und die Prozessseitentabelle aktualisieren.
Es gibt zwei Fälle: ein Fehler beim Lesen kann in eine Verbindung zu einer Seite von Null (spezielle globale vorgenuliste Seite) umgewandelt werden, die schreibgeschützt ist; und ein Fehler beim Schreiben (sowohl auf der nullseitigen als auch auf der nur erforderlichen, noch nicht physikalisch zugeordneten Seite) führt zu einer tatsächlichen privaten physikalischen Seitenzuordnung.
Für mmaps (und brk / sbrk, das ist auch intern mmap) ist diese Methode pro Seite; Alle mmaped-Regionen werden als Ganzes in vma registriert (sie haben Anfangs- und Endadressen). Stack wird aber anders behandelt, weil es nur eine Startadresse hat (höhere auf einer typischen Plattform; wachsen zu niedrigeren Adressen).
Die Frage ist:
Wenn ich auf neuen nicht zugewiesenen Speicher in der Nähe des Stacks zugreife, wird PF # erhalten und wachsen. Wie ist das Wachstum gehandhabt, wenn ich nicht auf die Seite neben dem Stapel stoße, sondern auf die Seite, die 10 oder 100 Seiten vom Stapel entfernt ist?
z. B.
%Vor%Erhält dieses Programm 2 oder 50 private physische Seiten, die für den Stack reserviert sind?
Ich denke, es kann profitabel sein, den Kernel zu bitten, Dutzende physischer Seiten in einer einzelnen Seite zuzuordnen, dann Dutzende Seitenvorgaben Seite für Seite zuzuordnen (1 Interrupt + 1 Kontextwechsel + einfache, Cache-freundliche Schleife über N Seitenzuweisungsanfragen gegenüber N Interrupts + N Context-switches + N Seitenzuweisungen, wenn mm-Code aus Icache entfernt werden kann.
Das automatische Wachstum des Stacks kann man sich als automatische Aufrufe von mremap
vorstellen, um die Größe der virtuellen Adresse zu ändern, die als "Stack" zählt. Sobald dies erledigt ist, werden Seitenfehler im Stapelbereich oder in einem Vanilla-mmap-Bereich gleich behandelt, d. H. Jeweils eine Seite.
Sie sollten also ~ 2 Seiten zugewiesen bekommen, nicht ~ 51. Perreals empirische Antwort bestätigt dies ...
Zu dem letzten Teil der Frage gehören die Kosten zusammenhängender Seitenfehler zu den Faktoren, die zur Entwicklung von "riesigen Seiten" führen. Ich glaube nicht, dass es in Linux noch andere Möglichkeiten gibt, die Seitenfehlerbehandlung zu "stapeln". Vielleicht könnte madvise
etwas tun, aber ich vermute, dass es hauptsächlich den wirklich teuren Teil von Seitenfehlern optimiert, der die Backingseiten im Speicher nachschlägt. Stack-Seitenfehler, die auf null Seiten abgebildet werden, sind im Vergleich relativ leicht.
Tags und Links linux memory-management linux-kernel page-fault