Hallo,
aber wen stört das?
Mich
Tja, pech!
Ich sollte mal erwähnen das ich mein OS dahin trimmen möchte, das es mit 4-8MB RAM lauffähig ist. Mein Fern-Ziel ist dann mit diesem RAM auch eine GUI zu haben (Win3.11 und Win95 haben das ja auch hinbekommen und laut der Meinung vieler ist Win Schrott und MS unfähig ).
Mit 4 bis 8 MB aus zu kommen ist schon ein ziemlich schwieriges Ziel. Vor allem ein hochperformanter SlabAllocator dürfte dem nicht gerade zuträglich sein weil er ja möglichst große Slabs will. Ich denke unter 32 bis 64 MB dürfte auch bei meinem OS nicht viel gehen, was vor allem am großzügigen SlabAllocator und daran das eine LDT 512 kBytes belegt liegt. Trotzdem bin ich der Meinung das, wenn mein OS bei 8GB RAM mit etlichen Programmen unter Action ist, es immer noch relativ sparsam mit RAM umgeht. Mein Designziel ist >1GB.
Ja wir reden vom selben Dokument.
Dann ist gut.
Du solltest die Blockgröße schon von der angeforderten Größe abhängig machen. Ein "new int" sollte also maximal eine 4KB-Page zurückgeben, ein "new buf[16M]" sollte 4 Pages je 4MB zurückgeben...
Für ein "new int" wird doch hoffentlich nicht eine eigene Page zurück gegeben sondern eher im Heap was passendes gesucht. Und wenn im Heap nichts mehr frei ist dann sollte die malloc-Implementierung auch nicht nur ne einzelne 4k-Page holen sondern vielleicht 128kB (oder ne ähnliche Größe) am Stück. Nur wenn malloc mehr als (sagen wir mal) 256kB am Stück zurück geben soll ist es vernünftig das direkt vom OS zu holen.
.....
Würde also so lange weitermachen, bis der reale Speicher bis aufs letzte Byte gefüllt ist.
Nur wenn er mit root-Rechten läuft, ansonsten bekommt er bereits vorher keinen neuen Speicher mehr (also nur noch NULL).
Was aber, wenn du übers Netzwerk swapst, dein TCP/IP-Stack aus Speichermangel größtenteils auf Platte liegt, der RAM randvoll ist und ein seltsames Paket im TCP/IP-Stack landet und verarbeitet werden muss? Du müsstest erstmal Teile deines TCP/IP-Stacks wieder in den RAM laden, wozu du Zeugs auslagern müsstest, was du nicht kannst, weil es den TCP/IP-Stack erfordert.
Erstmal finde ich ist TCP/IP ein wichtiger Treiber und sollte daher gar nicht ausgelagert werden (so fett wird der auch nicht sein das sich das lohnt) und außerdem schreibst Du da eher von komplexen Abhängigkeiten zwischen den Komponenten eines OS und die können noch ganz andere Probleme machen als nur knappen Speicher.
Naja, ich als Anwendungsprogrammierer erwarte schon von einem Flag, dass es exakt das tut, was ich möchte und nichts anderes.
Also ich erwarte das Flags genau das bewirkten was dokumentiert ist und nicht das was ich da gerne hinein interpretieren möchte. Wenn in der Doku steht das dieses Flag dazu dient dem OS zu sagen was ich machen will damit sich das OS möglichst optimal verhalten kann, falls es das auch wirklich kann, dann ist das Okay für mich. Es gibt ne Menge derartiger kann-Flags die eben dem OS sagen was für das Programm optimal wäre aber das OS nicht zu einem bestimmten Verhalten verpflichten. Solange das OS mir den Speicher, den ich in meinem virtuellen Adressraum haben will, auch wirklich
zusichern kann sollte der malloc-Syscall auch erstmal funktionieren. Ob die Pages alle sofort oder erst später eingeblendet werden macht ja funktional keinen Unterschied sondern beeinflusst
nur die Performance.
Daher würde ich eine Automatik machen (MAP_NOW wenn <16M, MAP_LAZY wenn größer). Ich bin der Meinung, dass kleine Blöcke sofort benutzt werden und große Blöcke nicht/teilweise.
Wenn wenn der Programmierer vom nächsten Programm Deine Meinung nicht kennt? Solche Automatismen haben immer den Nachteil das sie eben nie wirklich wissen was los ist sondern nur vermuten können und Vermutungen sind auch mal falsch (liegt in der Natur der Sache). Also da bevorzuge ich ein Flag das nur ne Empfehlung ist als das ich einen Automatismus haben möchte der von irgend welchen wagen Annahmen und Meinungen abhängt.
Niemals so, dass ich ein Flag explizit angebe und es dann ignoriert wird.
Du bist also der Meinung "lieber einen Syscall der nichts macht obwohl er eigentlich könnte wenn auch nicht ganz optimal als einen Syscall der versucht sich so gut wie möglich zu verhalten aber das nicht zusichert"? Diese Einstellung kann ich nicht nachvollziehen.
Sehe ich etwas anders, denn die Größe der "letzten Reserven" hängt von root ab. Wenn er nur "bash", "ps" und "kill" nutzen möchte, mag das sein - aber eventuell möchte er erstmal seine X11-Umgebung mit KDE starten, um darin nachzuschauen, was überhaupt kaputt ist...
Dann macht man die Größe der letzten Reserve eben konfigurierbar, entscheidend (für die Stabilität des OS) ist das es überhaupt eine gibt.
Ein root der bei Speicherknappheit erst mal KDE starten will ist IMHO auch selber schuld wenn das System mit Rums gegen die Wand fährt.
Daher bin ich der Meinung, dass - sofern im Kernel kein Speicher mehr da ist - der Prozess mit dem größten Speicherverbrauch gekillt werden sollte.
Also spätestens wenn Du mal nen halben Arbeitstag auf das Ende einer Simulation wartest und dann kurz vor Schluss das Simulationsprogramm noch mal etwas Speicher braucht und dann, nur weil es am
meisten Speicher braucht, vom OS gekillt wird entwickelst Du eine andere Meinung. Das ModelSim kann wimre mit NULL von malloc so umgehen das es fragt ob es noch mal malloc versuchen soll oder ob es die Simulation abbrechen soll (und man wenigstens den bereits fertigen Teil der Simulationsergebnisse noch verwenden kann). In der Zeit wo das Fragefenster wartet kann man auch schnell noch ein paar andere Programme schließen und danach erst mal auf den "nochmal"-Knopf drücken. Ein OS das einfach nach belieben irgendwelche Prozesse killt möchte ich nicht haben, lieber soll es keinen unprivilegierten Programmen neuen Speicher geben so das diese Programme die Möglichkeit haben angemessen zu reagieren.
Allerdings ist ein Programm, welches so viel RAM für sich in Anspruch nimmt, dass es das System nahezu lahmlegt für den Rechner dann ohnehin ungeeignet und man sollte das Programm anpassen oder RAM nachstecken.
Das ist ja prinzipiell richtig aber sollte ich als User nicht auch die Möglichkeit haben erst mal andere Programme weg zu räumen bevor das eine Programm, das meinen Rechner bis zum Anschlag auslastet, gekillt wird und diesem Programm die Gelegenheit geben doch noch fertig zu werden?
Ein System, was konstant am Anschlag lebt, sollte man überdenken.
Das ist immer eine Frage der Rahmenbedingungen. Ich als Privatperson werde mir nicht einen neuen Rechner kaufen nur weil ich einmal im Monat ein Programm benutze das meinen Rechner bis an die Grenze bringt. Solange es doch noch irgendwie geht möchte ich diese Geldausgabe lieber vermeiden. Erst wenn das Programm dann doch die Grenze überschreitet so das ich keine Chance habe das durchlaufen zu lassen bin ich wirklich gezwungen einen neuen Rechner zu kaufen, ich erwarte von meinem OS das es mir ermöglicht es wenigstens zu versuchen ob das Programm irgendwie zum Abschluss kommt.
Wenn du allgemeine Treiber nutzt, ist das nicht möglich; deren Speicheranforderung kann sich stark unterscheiden, je nach Auslastung.
Durch was schwankt der Speicherverbrauch eines Treibers so stark? Wenn ich jetzt mal an einen SATA-AHCI-Treiber denke dann bekommt der maximal wie viele Jobs gleichzeitig? Sagen wir mal 100 und nehmen für jeden Job mal 4 kB zur internen Verwaltung (ist das zu wenig?) dann schwankt der RAM-Bedarf dieses Treiber um maximal 400kB. Wo ist da das Problem? Das sollte die malloc-Implementierung doch recht gut abfangen können so das der Treiber normalerweise gar keine Speicheranforderungen an den Kernel schickt.
Außerdem willst du wirklich 25% des RAMs für root reservieren? Das stelle ich mir grad in einem Rechenzentrum mit 64 GB RAM/Node vor...
Die 25% waren doch nur mal so dahingeschrieben, es wäre natürlich besser wenn man das konfigurieren kann so das root eben klar festlegen kann was er im Notfall als Reserve wirklich braucht (zuzüglich einen gewissen Überhang fürs OS).
Ich glaube Du hast nicht ganz verstanden was ich eigentlich ausdrücken wollte. Es geht mir nicht um Datenbanken o.ä. sondern um ein Szenario in dem ein Programm einen großen Bereich an virtuellem Speicher benötigt und diesen auch mit echten Daten befüllt aber dann zur weiteren Laufzeit nur einen kleinen Anteil davon tatsächlich benutzt, das bedeutet das von diesem Bereich durchaus ein hoher Anteil an Pages ausgelagert sein können ohne dass das negative Konsequenzen (für die Performance) hat. Das selbe trifft auch auf übliche Code-Bereiche zu, kaum ein Programm wird ständig all seinen Programm-Code ausführen.
Ich hab das schon so verstanden.
Sicher? Diesen Eindruck habe ich irgendwie nicht.
Ursprünglich ging es aber um die Verwaltung des virtuellen Speichers - jeder dort vorhandene Block wird (in meiner Welt) durch mehrere Pages ausgedrückt, d.h. die Verwaltung, welche Pages nun wirklich im RAM sind, liegt anderswo. Und wenn deine Rechtschreibprüfung jedes Wort in eine eigene Page (mit eigenem malloc) stopfen will, dann wird die Anwendung halt langsam. Der aktuelle Auslagerungszustand ist davon unabhängig und ich muss Blöcke auch nicht unbedingt vollständig ausgelagert haben.
Was hat das alles mit vollständig belegten aber nur dünn benutzen virtuellem Speicher zu tun? Wieso sollte ich für eine Rechtschreibprüfung jedes Wort in eine eigene Page legen?
Wenn man nur ein kleines schnelles Programm oder einen eigenen Allocator schreiben will, wird man genau solch einen Syscall nutzen.
Dann muss man sicher aber auch mit der exakten Funktionsweise des OS beschäftigen und sollte auch nicht jeden Speicherbedarf in 4kB-Häppchen decken sondern sich überlegen wie das Programm den Speicher benutzen möchte und in entsprechender Größe die Blöcke holen. Da fällt mir ein: willst Du bei Deinem Speicher-Mapping-Syscal für den virtuellen Speicher vorgeben können wo hin der Kernel die neuen Pages in den virtuellen Adressraum des Prozesses legen soll? Wenn ja dann lohnt es sich eventuell schon den virtuellen Speicher, der von der malloc-Implementierung für den Heap benutzt wird, in sehr kleinen aber zusammenhängenden Schritten zu vergrößern.
Ich hab nen Mikrokernel und da sollte sich die API nun wirklich nicht ändern
Warum nicht? Kann es nicht mal sein das Du zu einem bereits bestehenden Syscall noch ein Parameter hinzufügen möchtest?
und wenn sie es doch tut, dann so schlimm das du das auch über Libraries nicht abfangen kannst.
Trifft das auch auf Programme zu die nur von der libc (kein POSIX oder sonstwas) abhängig sind?
Es ist ja gerade die Aufgabe von Librarys sowas abzufangen und das funktioniert oft sogar über viele OSe hinweg, also warum soll das nicht zwischen verschiedenen Versionen eines OS funktionieren?
Wir sind immernoch bei der Speicherverwaltung und da behaupte ich mal das die besseren Engines kein libc malloc() sondern ihren eigenen Allocator benutzen und dieser ruft direkt die Speicher-Funktionen vom OS auf (würde ich jedenfalls so machen, zwecks Performance).
Die Hersteller der besseren Engines kaufen sich eine ordentlich hochperformante malloc-Implementierung (und bleiben in ihrem Code bei malloc).
das wenn kein Lock benutzt wird, eine Semaphore benutzt wird, aber die lohnt sich halt erst, wenn der kritische Bereich wirklich lange dauert (meine Meinung und ich weiß das erik das anders sieht).
Dann musst Du erst mal genau erklären was für Dich der Unterschied zwischen einem Lock und einer Semaphore ist. In meinem Kernel wird es nur simple Locks und eventuell Reader/Writer-Locks (obwohl mir da jetzt im Moment gar kein Anwendungsfall für einfällt) geben.
Grüße
Erik