Linux-Kernel: Linux 5.17 mit neuem AMD-Powermanagement

Seite 2: Problem Anonymität

Inhaltsverzeichnis

Einen späten Siegeszug erhält eine Idee aus dem Jahr 2013, die dem anonymen Arbeitsspeicher zu Leibe rückt und ihn seiner "Anonymität" ein wenig beraubt. Grundsätzlich können zwei Arten von Speicher im Userspace zum Einsatz kommen. Die "file-backed Pages" stehen in direktem Bezug zu persistentem Speicher, also einer Datei auf Platte. Ist die Page "sauber" (clean), stimmen Inhalt auf Disk und im Arbeitsspeicher überein. Die "anonymous Pages" hingegen haben keine feste Repräsentation auf der Disk. Sie liegen erst mal nur im Arbeitsspeicher. Auf Festplatte gelangen sie nur im Zuge des Swapping. In diesem anonymen Speicher liegen Datensegmente oder auch der Stack eines Prozesses.

"File-backed Pages" lassen sich leicht über die repräsentierende Datei identifizieren. Anonymer Speicher hingegen nicht. Daher auch sein Name. Derartige Speichersegmente können über verschiedene Allokatoren erzeugt werden. Unter Linux sind das malloc() (libc), der Stapel sowie direkte Syscalls. In einer Umgebung mit virtuellen Maschinen kommen noch mehrere VM-Heaps hinzu. Für jede dieser Allokatoren existieren bestenfalls eigene Tools, um den Speicher zu inspizieren und so Optimierungsbedarf zu erkennen. Eine Gesamtsicht fehlt. Der Kernel konnte auch bislang keinen Ansatz bieten, eine solche zu liefern. Er sieht nur absolut anonyme Pages ohne Quellenangabe.

Eine kniffelige Herausforderung stellt sich auch beim Ermitteln des physischen Speicherbedarfs eines Prozesses, wenn dieser "shared Memory" nutzt. Ist aller anonymer Speicher nicht unterscheidbar, ist es nicht mit einfachem Aufaddieren der Pages eines Prozesses getan, um den wahren physischen Speicherbedarf desselben zu ermitteln. Um einen konsistenten Blick auf den physischen Speicher zu erhalten, wäre vor Linux 5.17 ein "Rundgang" durch alle Pages notwendig.

Der neue Kernel erweitert prctl() um die Operation

prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, start, len, name)

Damit können Userspace-Prozesse einem Speicherbereich (Virtual Memory Area, VMA) einen Namen in Form eines Strings zuweisen. Die VMA ist mit ihrer Startadresse start und der Länge len definiert. Auf diese Weise kann jeder Allokator durch ihn reservierten Speicher mit einem Namen versehen. Gleiche Namen verschiedener Pages deuten auf gleiche Allokatoren als Quelle hin. Auf diese Weise lässt sich der anonyme Speicher seinem Urheber zuordnen.

Diese nun umgesetzte Lösung basiert auf einem ursprünglich 2013 bereits von Colin Cross eingereichtem Patch. Der Patch schaffte es damals nicht in den Mainline-Kernel, da Zeiger im Userspace zum Speichern der VMA-Namen genutzt wurden. Insbesondere Kees Cook hatte Bedenken zur Sicherheit und Performance und schlug das Speichern des Namens im Kernel-Space sowie Validitätschecks vor.

Zudem gab es berechtigte Bedenken beim Erzeugen von Kindprozessen mittels fork(). Da hierbei ein Elternprozess eine Kopie von sich selbst als Vorlage des Kindprozesses erzeugt, müssen alle seine Speicherbereiche kopiert werden. Dabei wären auch alle Strings der VMA-Namen mittels strdup() zu kopieren. Das würde das System erheblich in der Leistung beeinträchtigen, wie auch Experimente deutlich zeigten. So führte der fork() eines Prozesses mit 64KB großen VMAs und Namen-Strings von Maximallänge zu einer Worst-Case-Regression von fast 40 Prozent.