Hallo,
für malloc/free ist nicht das OS zuständig sondern die libc innerhalb der Applikation, also Teil des User-Mode-Codes. Mit malloc/free wird der Heap benutzt und wie dieser intern verwaltet wird ist je nach Realisierung der libc ziemlich unterschiedlich. Da gibt es von ganz simplen verketteten Listen bis hin zu komplexen SLAB-Allocatoren eine ordentlich große Bandbreite ab Möglichkeiten. Letztlich bauen diese aber alle auf den normalen virtuellen Speicher auf den die Applikation vom OS bekommt, zumindest auf einem normalen Flat-Memory-System. In diesem Punkt unterschieden sich Windows und Linux (und auch alle anderen OSe in dieser Klasse) nur marginal von einander.
Was alle aktuellen OSe gemeinsam haben ist die Art mit der sie den virtuellen Speicher den Applikationen zur Verfügung stellen also das Paging, was eben der Grundstein des Flat-Memory-Konzepts darstellt. Paging ist zwar eine tolle Idee aber hat einen erheblichen Nachteil: es kostet bei jedem Speicherzugriff Performance. Das wird zwar mit Dingen wie dem TLB noch einigermaßen gut abgefangen aber spätestens wenn reale Programme mal wirklich ein paar TB an echtem Speicher benötigen und auch benutzen wollen dürfte das Konzept des TLB an seine Grenzen geraten sein und der Performanceverlust fürs Paging enorm werden. Deswegen möchte ich das mit Segmenten machen, die kosten deutlich weniger Performance und das ist auch nicht davon abhängig wie viele Segmente ein Programm insgesamt nutzt oder wie groß diese Segmente sind. Das einzigste was passen muss ist die Anzahl der Segment-Register (wovon x86 leider viel zu wenige hat so das dort Segmentierung nie wirklich zufriedenstellend war, nebst dessen das Segmentierung bei x86 auch nur schlecht im Befehlssatz integriert ist).
Für meine Heap-Implementierung, innerhalb der libc, will ich auch ein paar Segmente benutzen (die per Syscall vom OS geholt und verwaltet werden). Ich denke das ich es schaffe damit eine recht kleine innere Fragmentierung zu erreichen aber dafür habe ich das Risiko einer externen Fragmentierung also die einzelnen Segmente werden den physischen Speicher langsam fragmentieren (wie die Dateien auf einer Festplatte). Vor allem wenn die Speichernutzung sich langsam der Größe des physischen Speichers nähert wird das ein dringenderes Problem. Deswegen möchte ich die Möglichkeit haben für einzelne Segmente individuell Paging aktivieren zu können. Auf diese Art bleibt das Segment aus Sicht der Applikation intakt obwohl es über den physischen Speicher verstreut also fragmentiert ist. Das Paging ermöglicht es dann auch dieses Segment im Hintergrund, also ohne das die Applikation das merkt (vom Performanceverlust mal abgesehen), zu defragmentieren. Sobald das Defragmentieren der Segmente im physischen Speicher abgeschlossen ist kann das Paging wieder deaktiviert werden und die betreffende Applikation läuft wieder mit voller Performance.
Mir ist bewusst das ich mir damit einiges an Problemen aufhalse (z.B. was passiert wenn ein Segment vergrößert werden soll während es defragmentiert wird? gerade in einem SMP-System kann ja theoretisch beides gleichzeitig passieren) aber ich denke das sich das unterm Strich trotzdem lohnt. In den modernen Flat-Memory-OSen versucht man ja auch eine Art Defragmentierung einzubauen damit z.B. viele 4kB-Pages zu einer 2MB-Page zusammengefasst werden können, mit steigendem realen Speicherverbrauch der Applikationen wird das auch immer nötiger werden um den Performanceverlust durchs Paging in Grenzen zu halten.
Für mein System betrachte ich Paging nicht als Mittel gegen Fragmentierung, die wird bei meinen Segmenten zwangsläufig auftreten, sondern eher als Werkzeug um diese Fragmentierung wieder zu beheben. Auch fürs Swapping ist IMHO Paging die einzigst praktikable Lösung. Daneben eröffnet mir das Paging auch Dinge wie Memory-Mapped-File-IO aber das kommt erst sehr viel später dran. Im übrigen werden bei mir Segmente auch immer nur ganze Pages belegen und in jeder Page wird immer nur maximal ein Segment drin sein, so ähnlich wie ein Cluser bei FAT auch immer nur von einer Datei benutzt werden kann. Die Verwaltung des physischen Speichers in meinem OS wird also auch nur mit Pages arbeiten. Der wesentliche Unterschied zwischen Segmentierung und Paging ist der das für Segmentierung eine Basis und eine Größenangabe reicht um jedes Offset das innerhalb des Segments liegt in eine physische Adresse umrechnen zu können wogegen bei Paging riesige Tabellen erforderlich sind um eine virtuelle Adresse in eine physische Adresse umwandeln zu können.
In normalen Programmiersprachen, wie z.B. C, sind lokale Variablen (innerhalb von Funktionen) immer auf dem Stack und nicht auf dem Heap. Bei Java landet alles auf dem Heap, ist dort ein wesentlicher Aspekt des Gesamtkonzepts, und man kann als Programmierer auch nicht explizit zwischen Heap und Stack wählen aber bei vielen anderen Programmiersprachen wird zwischen Heap und Stack klar unterschieden und der Programmierer hat auch die Wahl was er benutzen möchte. Ich vermute Du solltest Dir einfach mal noch ein paar andere Dinge abseits von Java genauer ansehen um einen besseren Überblick über die vielfältigen Möglichkeiten zu bekommen.
Grüße
Erik
für malloc/free ist nicht das OS zuständig sondern die libc innerhalb der Applikation, also Teil des User-Mode-Codes. Mit malloc/free wird der Heap benutzt und wie dieser intern verwaltet wird ist je nach Realisierung der libc ziemlich unterschiedlich. Da gibt es von ganz simplen verketteten Listen bis hin zu komplexen SLAB-Allocatoren eine ordentlich große Bandbreite ab Möglichkeiten. Letztlich bauen diese aber alle auf den normalen virtuellen Speicher auf den die Applikation vom OS bekommt, zumindest auf einem normalen Flat-Memory-System. In diesem Punkt unterschieden sich Windows und Linux (und auch alle anderen OSe in dieser Klasse) nur marginal von einander.
Was alle aktuellen OSe gemeinsam haben ist die Art mit der sie den virtuellen Speicher den Applikationen zur Verfügung stellen also das Paging, was eben der Grundstein des Flat-Memory-Konzepts darstellt. Paging ist zwar eine tolle Idee aber hat einen erheblichen Nachteil: es kostet bei jedem Speicherzugriff Performance. Das wird zwar mit Dingen wie dem TLB noch einigermaßen gut abgefangen aber spätestens wenn reale Programme mal wirklich ein paar TB an echtem Speicher benötigen und auch benutzen wollen dürfte das Konzept des TLB an seine Grenzen geraten sein und der Performanceverlust fürs Paging enorm werden. Deswegen möchte ich das mit Segmenten machen, die kosten deutlich weniger Performance und das ist auch nicht davon abhängig wie viele Segmente ein Programm insgesamt nutzt oder wie groß diese Segmente sind. Das einzigste was passen muss ist die Anzahl der Segment-Register (wovon x86 leider viel zu wenige hat so das dort Segmentierung nie wirklich zufriedenstellend war, nebst dessen das Segmentierung bei x86 auch nur schlecht im Befehlssatz integriert ist).
Für meine Heap-Implementierung, innerhalb der libc, will ich auch ein paar Segmente benutzen (die per Syscall vom OS geholt und verwaltet werden). Ich denke das ich es schaffe damit eine recht kleine innere Fragmentierung zu erreichen aber dafür habe ich das Risiko einer externen Fragmentierung also die einzelnen Segmente werden den physischen Speicher langsam fragmentieren (wie die Dateien auf einer Festplatte). Vor allem wenn die Speichernutzung sich langsam der Größe des physischen Speichers nähert wird das ein dringenderes Problem. Deswegen möchte ich die Möglichkeit haben für einzelne Segmente individuell Paging aktivieren zu können. Auf diese Art bleibt das Segment aus Sicht der Applikation intakt obwohl es über den physischen Speicher verstreut also fragmentiert ist. Das Paging ermöglicht es dann auch dieses Segment im Hintergrund, also ohne das die Applikation das merkt (vom Performanceverlust mal abgesehen), zu defragmentieren. Sobald das Defragmentieren der Segmente im physischen Speicher abgeschlossen ist kann das Paging wieder deaktiviert werden und die betreffende Applikation läuft wieder mit voller Performance.
Mir ist bewusst das ich mir damit einiges an Problemen aufhalse (z.B. was passiert wenn ein Segment vergrößert werden soll während es defragmentiert wird? gerade in einem SMP-System kann ja theoretisch beides gleichzeitig passieren) aber ich denke das sich das unterm Strich trotzdem lohnt. In den modernen Flat-Memory-OSen versucht man ja auch eine Art Defragmentierung einzubauen damit z.B. viele 4kB-Pages zu einer 2MB-Page zusammengefasst werden können, mit steigendem realen Speicherverbrauch der Applikationen wird das auch immer nötiger werden um den Performanceverlust durchs Paging in Grenzen zu halten.
Für mein System betrachte ich Paging nicht als Mittel gegen Fragmentierung, die wird bei meinen Segmenten zwangsläufig auftreten, sondern eher als Werkzeug um diese Fragmentierung wieder zu beheben. Auch fürs Swapping ist IMHO Paging die einzigst praktikable Lösung. Daneben eröffnet mir das Paging auch Dinge wie Memory-Mapped-File-IO aber das kommt erst sehr viel später dran. Im übrigen werden bei mir Segmente auch immer nur ganze Pages belegen und in jeder Page wird immer nur maximal ein Segment drin sein, so ähnlich wie ein Cluser bei FAT auch immer nur von einer Datei benutzt werden kann. Die Verwaltung des physischen Speichers in meinem OS wird also auch nur mit Pages arbeiten. Der wesentliche Unterschied zwischen Segmentierung und Paging ist der das für Segmentierung eine Basis und eine Größenangabe reicht um jedes Offset das innerhalb des Segments liegt in eine physische Adresse umrechnen zu können wogegen bei Paging riesige Tabellen erforderlich sind um eine virtuelle Adresse in eine physische Adresse umwandeln zu können.
In normalen Programmiersprachen, wie z.B. C, sind lokale Variablen (innerhalb von Funktionen) immer auf dem Stack und nicht auf dem Heap. Bei Java landet alles auf dem Heap, ist dort ein wesentlicher Aspekt des Gesamtkonzepts, und man kann als Programmierer auch nicht explizit zwischen Heap und Stack wählen aber bei vielen anderen Programmiersprachen wird zwischen Heap und Stack klar unterschieden und der Programmierer hat auch die Wahl was er benutzen möchte. Ich vermute Du solltest Dir einfach mal noch ein paar andere Dinge abseits von Java genauer ansehen um einen besseren Überblick über die vielfältigen Möglichkeiten zu bekommen.
Grüße
Erik

Übersicht
Wiki
Hilfe
Suche
Einloggen
Registrieren
Drucken

Gespeichert


