Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Nachrichten - FlashBurn

Seiten: 1 ... 23 24 [25] 26 27 ... 43
481
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 15. November 2010, 12:02 »
Zitat von: erik
Der Heap ist der Mechanismus der dem User-Code Speicher zur Verfügung stellt, der entscheidende Punkt ist das der User-Code beliebig große Speicherstückchen anfordern darf und der Heap-Mechanismus dafür sorgen muss das da trotzdem möglichst wenig Verschnitt entsteht. Darüber hinaus ist es Aufgabe des Heap-Mechanismus ein einheitliches API (malloc/free) zur Verfügung zu stellen und die konkreten OS-Funktionen dahinter zu verstecken (wegabstrahieren).
Also können wir uns darauf einigen das der Heap == malloc()/free() ist!?

Mein Prof hat mich heute auch wieder "geärgert". Denn ich sehe es immernoch soch das malloc()/free() nichts mit dem OS zu tun zu haben. Die stehen in irgendeiner Library drin und das OS hat keine Kontrolle darüber. Genauso kann man malloc()/free() oder die Library einfach austauschen ohne dass das OS was an der Speicherverwaltung ändert.

Was mich halt dann immernoch irretiert, ist wenn Leute sagen das die UserSpace Speicherverwaltung auch komplett vom UserSpace gemacht wird (eigentlich meinen die den Heap, aber dann sollen sie es auch sagen!) und das ist halt nicht so. Der Heap kann sich bei mir halt nicht aussuchen wo neuer Speicher hingemappt wird, sondern er hat das zu nehmen was er vom OS bekommt.

Zitat von: erik
Doch, gerade Du als OS-Entwickler musst festlegen wie die Heap-Implementierung von der zu Deinem OS gehörenden libc arbeiten soll.
Siehe oben. Was ist wenn ein Programm aber ne andere libc verwendet. Alles was im UserSpace stattfindet hat mit dem OS nichts mehr zu tun (in dem Sinne das du es bestimmen kannst, mal von Apple abgesehen ;) ).

Zitat von: erik
Trotzdem bin ich der Meinung das man die Verwaltungsinformationen von den Nutzdaten trennen sollte.
Ich sage mal das du dadurch mehr Verschnitt haben wirst und wahrscheinlich sogar langsamer sein wirst (wie reden von FlatMemory ;) ).

Zitat von: erik
Für den User-Space könntest Du dort den Page-Mapping-Counter (für Pages die in mehreren Adressräumen gemappt sind) unterbringen, im Kernel wirst Du doch hoffentlich kein Shared-Memory machen.
Doch im Kernel habe ich auch SharedMemory und ich will der Struktur (die in einem Array organisiert ist) ja noch ein Element von 4Byte Größe hinzufügen, aber nicht nur weil es den SlabAllocator im Kernel schneller macht (und Speicher spart).
Damit der Speicher den ich sparen würde sich auch rentiert, müsste ich mind. 209715 Slabs in meinem Kernel haben und ich denke das sollte nicht so einfach passieren.

Zitat von: svenska
Der sortiert nicht (er nimmt vorne weg und hängt hinten an) und er sucht nicht (er nimmt immer das erste Element). Definiere "sortieren" und "suchen".
Ich füge neue Threads sortiert ein, also sortiere ich und ich suche immer den Thread mit der größten Priorität, also suche ich!
Das selbe mit dem geposteten Allocator, der sucht und sortiert auch, er macht halt nur ein paar Annahmen, naund!

Zitat von: svenska
Wenn dein Quicksort feststellt, dass der Stackspace voll ist, dann müsstest du in jedem Fall einen weiteren Aufruf machen
Ich habe gesagt, dass man das vorher entscheiden muss! Nicht erst mittendrin.

Zitat von: svenska
Dann musst du die Anzahl der Threads beschränken (macht sich im Hinblick auf Scheduler und andere Dinge im System eh besser),
Das hieße aber das ich bei vielen Sachen gar nicht die Performance bekomme die ich haben könnte und das die Anwendung nicht skaliert und das geht heutzutag gar nicht!

Zitat von: svenska
Damit löst du aber die Aufgabe nicht mehr.
Das stimmt ja so nicht. Wenn du in Physik (Schule) die Aufgabe bekommst, irgendetwas zu berechnen, machst du auch viele Annahmen, damit du die ganze Rechnung vereinfachen kannst.
Genauso macht man das bei vielen Problemen in der Informatik (frag mich bitte nicht nach einem Bsp.).

Zitat von: svenska
was O(1) eigentlich bedeutet
Die Anzahl der Schritte ist immer gleich.

Zitat von: svenska
Ein malloc(1) dauert exakt genausolange wie ein malloc(1024*1024*1024) und ist unabhängig vom derzeitigen Zustand des physischen Speichers?
Was das malloc() betrifft ist dem so. Ich kann bei so einer Betrachtung nicht noch das OS mit einbeziehen. Denn es kann ja sein das ich gar nicht weiß wie das OS es macht oder auf welchen OS mein Code läuft. Trotzdem kann malloc() O(1) sein.

[quote="svenska"
Ein Array ist bei bekanntem Index O(1), bei unbekanntem Index (=Suche) O(n), maximal O(log n).
[/quote]
Der Index dieses speziellen Arrays ist bekannt (ist einfach die Nummer der physischen Page).
482
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 14. November 2010, 18:14 »
Zitat von: erik
Hast Du da ein paar Vorschläge
Naja, das Standardboard schlecht hin was osdev betrifft (behaupte ich mal) http://forum.osdev.org/index.php. Ob die mit deiner Idee klarkommen, weiß ich aber nicht.

Zitat von: erik
Du machst den Heap für den User-Mode im Kernel? Und dann noch Page-basiert? Gibt es dann jedes mal 4032 Bytes Verlust wenn ich ein Objekt mit 64 Bytes allozieren will?
Genau deswegen wäre es toll wenn mir mal jemand erklärt was der Heap ist und was er macht. Denn was du mit Heap meinst, ist doch einfach nur malloc() und malloc() ruft entweder sbrk() oder mmap() auf um neuen Speicher zu bekommen.
Und genau letzteres meine ich! Was und wie malloc() dann den Speicher organisiert weiß ich nicht bzw. lege ich nicht fest.
Für mich ist der Heap einfach nur ein Speicherbereich der von malloc() genutzt wird und Page-basiert ist. Bei mir ist dieser Speicherbereich nur nicht zwingend zusammenhängend.

Zitat von: erik
Das klingt nicht sehr vertrauenerweckend, das kann doch die Applikation ganz schnell mal kaputt machen und dann ist die Hölle los.
Sorry, aber jetzt kommt bei mir wieder Unverständnis! Ihr (du und svenska) sagt, dass ein "Verbraucher" seine Ressourcen so wieder zurück gibt wie er sie bekommen hat (also nicht 3 IDs miteinmal), aber hier sagst du jetzt dass das ja doof ist und das Programm amok laufen kann.
Ist bei nem SlabAllocator nicht anders, da musst du auch darauf vertrauen das die Adresse die freigegeben werden soll auch die richtige ist.
Alles andere wäre aber auch entweder Speicherverschwenderisch und/oder langsam.

Zitat von: erik
Das ist aber IMHO nichts für den User-Mode-Heap, für den Kernel selber sieht das aber schon recht interessant aus.
Das weiß ich ja, aber ich finde es halt auch nicht so toll, wenn man für max 1GB (von 4 möglichen) Speicher verbraucht das aber für den Rest nicht nutzen kann.
Deswegen, nochmals die Frage was man in so einem Pointer/Wert noch speichern könnte, was für den Kernel vllt ganz interessant sein könnte?

Zitat von: erik
Ich will ja nicht schon wieder die Segmente erwähnen aber mit denen ist dieses Problem recht einfach zu lösen.
Wenn man den Stack wirklich nur für lokale Variablen nutzen würde und nicht die Adressen von diesen Variablen nutzen/brauchen würde, dann könnte man ganz einfach auch unter PM im 32bit Modus Segmente für den Stack nutzen. Damit wäre das Problem auch gegessen und der Compiler müsste es nicht mal wissen.
483
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 14. November 2010, 11:11 »
Zitat von: erik
Du warst es doch der hier mehrfach für neue Wege plädiert hat.
Ich sag ja auch gar nichts gegen neue Wege oder deine Architektur, es ist halt das Problem, dass deine Architektur noch nicht in Hardware existiert, das ich (oder wer auch immer) sie nicht haben kann und das ein OS welches für Segmente geschrieben (und optimiert) wurde sehr schlecht auf ne FlatMemory Architektur portierbar sein dürfte.

Zitat von: erik
umgedreht erscheint mir das ziemlich selten (jedenfalls kann ich mich nur vereinzelt daran erinnern gut auf Segmentierung passende Antworten bekommen zu haben).
Das könnte daran liegen das es nicht so einfach zu verstehen ist ;) Ich habe jedenfalls immernoch Probleme damit.

Zitat von: erik
aber wenigstens etwas Toleranz wäre nicht schlecht.
Ach ich denke Toleranz ist nicht das Problem. Es ist halt nur doof wenn einer sagt, ich habe hier folgendes Problem ... und du dann antwortest, auf meiner Architektur mit meinen Segmenten würde ich das so und so lösen. Ist zwar schön zu wissen, aber geholfen hat es nichts ;)

Für sowas wäre es am besten wenn du extra Threads aufmachst (Problem wäre wahrscheinlich das sich kaum Leute finden lassen die dann mit diskutieren können/wollen) oder die Diskussion so allgemein gehalten wird das es für beides gilt.

Hast du es eigentlich schonmal versucht deine Architektur in anderen Foren vorzustellen und die Feedback/Meinungen einzuholen (nichts gegen die Leute hier, aber es gibt Foren, wo ich mal behaupte das sich mehr und fähigere Leute rumtreiben)?

Zitat von: erik
Aber auch der kann seine Objekt-Pools nicht als beliebig großes Array (mit O(1)-Komplexität) verwalten (das ist das was ich mache) sondern muss die in mehreren Stücken (die Slabs) über den einen virtuellen Adressraum verteilen.
Das ist z.B. glaub ich ein Punkt wo sich mein OS von anderen unterscheidet. Denn bei mir macht das nicht der User sondern der Kernel. Du rufst nur den Kernel auf das du neuen Speicher brauchst und wieviel und bekommst (sofern genug virtueller Speicher frei ist) nen Pointer auf solch einen Bereich zurück.
Bei mir besteht der SlabAllocator im Endeffekt nur aus erstes Element der Liste entfernen und Element an den Anfang der Liste packen.
Was bei mir nicht O(1) ist, ist unter Umständen das Suchen nach der Liste (unter Linux geht das).

Zitat von: erik
Mich würde in diesem Zusammenhang mal interessieren wie das free von dem übergebenen Pointer auf die Objekt-Größe schließen kann um es dann auch in den richtigen Verwaltungsstrukturen als frei zu markieren.
Dafür gibt es mehrere Möglichkeiten, einmal hat man BoundaryTags (also vor dem Pointer steht wie groß der Bereich ist und eventuell mehr) und einmal speicherst du die Info welcher Slab-Struktur verwendet wird in der Struktur für die physische Page (unter Linux wird das so gemacht, aber das verbraucht mir zu viel Speicher).

Um mal die Möglichkeit von Linux zu diskutieren. Die haben ja ne page_t Struktur, wo die so einige Infos speicher, z.B. wie oft ne Page gemappt ist, sowas ähnliches habe ich ja auch (ist ein großes Array) und wenn ich wollte könnte ich dieses Array bzw. die Elemente darin ja um 4Byte größer machen damit ich darin nen Pointer auf ne Slab-Struktur speichern könnte.
Dazu hätte ich dann mal 2 Fragen. Ich sehe es halt so das der Speicherverbrauch eigentlich zu hoch dafür ist (die paar Pages die in meinem Kernel dann gemappt werden, max 1GB) oder wie seht ihr das?
Das nächste ist, was könnte man in so einem Pointer/Wert noch speichern, damit es sich doch lohnen würde das zu nutzen?

Problem was ich sehe, ist das es nur Infos sein dürfen die ich im Kernel brauchen könnte. Denn extra nen Syscall zu machen um die Info aus diesem Pointer zu bekommen, kostet mehr Performance als sie bringen würde und ist ein Sicherheits-Problem.

Zitat von: erik
Mein Angriff von http://forum.lowlevel.eu/index.php?topic=2224.msg25456#msg25456 funktioniert auch bei 64 Bit.
Ich habe mir jetzt nicht alles durchgelesen, aber es läuft ja darauf hinaus, das ne Guard-Page von 4KB unzureichend erscheint, da man mit nem Index von nem Array leicht über diese Grenze hinauskommt.
Ich sehe es eigentlich so, na und! Ist ein Fehler des Programms und entweder es schmiert ab (weil keine Zugriffsrechte) oder es wird was überschrieben und schmiert dann ab oder es kann fremder Code ausgeführt werden. Bei letzterer Variante ist halt das Programm schuld, sicher sollte man als OS versuchen so gut es geht sich auch vor solchen Problemen zu schützen, aber ich weiß nicht ob das Verhältnis von Aufwand Nutzen da so toll ist.
484
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 14. November 2010, 08:09 »
Zitat von: svenska
Zeige mir bitte einen O(1) Sortier- und einen O(1)-Suchalgorithmus.
Schonmal was von nem O(1) Scheduler gehört, der macht ja im Endeffekt auch nichts anderes als sortieren und suchen. Du musst die Menge der Elemente nur weit genug einschränken und schon geht das ;)

Bestes Bsp. wäre sogar ein malloc() wo ein SlabAllocator dahinter steckt der nur Blöcke mit 2er Potenzen hat.

Und ein anderes Bsp. was ich neulich gefunden habe: http://rtportal.upv.es/rtmalloc/

Zitat von: svenska
Vergleiche mal die Laufzeit von Bubblesort und Quicksort für n Elemente (1k < n < 100k) und entscheide dann, ob dir solche Lösungen gefallen oder du nicht lieber doch den Stack allgemein größer baust. RAM ist heutzutage billig und in ausreichender Menge verfügbar.
Aber was ist mit meiner Idee QuickSort halt in Schritten anzuwenden?

Zumal es ja darum ging das du ab einer bestimmten Anzahl von Threads die Stacks nicht mehr vergrößern kannst und da hilft dann auch mehr RAM nicht mehr, sondern eine Lösung ist 64bit Architektur.

Die andere Lösung wären Stacks die nicht zusammenhängend sind. Ich habe sowas mal im Zusammenhang mit Linux gelesen, weiß aber nicht mehr wo das war oder wie das funktionieren soll.

Zitat von: svenska
Und wenn eine Aufgabe schon theoretisch nur in O(n^2) lösbar ist, so trifft dies auf jede noch so geniale Implementation zu (oder schlechter).
Wimre dann hatte ich in theoretischer Informatik mal, das man bei genau solchen Problemen sich einfach "bessere" Bedingungen (z.B. die Menge der Elemente einschränken o.ä.) schafft damit man die Probleme halt schneller lösen kann.
485
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 13. November 2010, 21:46 »
Zitat von: erik
Und warum ist gerade das "normal"? Und jetzt komm mir bitte nicht mit Statistik!
Normal ist für gewöhnlich das was die Mehrheit ist und das dürften FlatMemory Modelle sein. Ich weiß auch nicht warum dem so ist, aber es wird schon seinen Grund haben.

Zitat von: erik
Und genau diesen Sortierzustand kennt man nicht im voraus! Also ist es besser wenn der Stack in seiner Größe möglichst flexibel ist und gerade das kann ein Flat-Memory-OS eben nicht bieten.
Und trotzdem wird QuickSort benutzt, was mir sagt, das es irgendwie lösbar ist. Zumal müsstest du doch den worst-case anhand der Datenmenge abschätzen können bzw. spontan fällt mir ein,halt nen QuickSort zu "simulieren". Ich meine damit, dass du deine Datenmenge in mehrere Teile einteilst und die erst sortierst (im Endeffekt das was QuickSort macht) und wenn du die sortiert hast, sortierst du die ganze Datenmenge, da die Teilmengen schon sortiert sind, müsste das ganze ja jetzt mit weniger Rekursionen auskommen.
Es gibt immer einer Lösung ob die schnell und elegant ist sei mal dahin gestellt.

Zitat von: erik
(natürlich nur wenn man unabhängige Segmente hat)
Es ist schön das du uns die Vorteile deiner Architektur zeigen kannst, aber was die Diskussion betrifft ist das immer schlecht, weil wir ja eigentlich Probleme diskutieren die eine FlatMemory Architektur betrifft.
Das wäre wie, ich habe nen Algo gefunden der alle anderen auf Single CPU Systemen schlägt, aber auf SMP Systemen ist er grotten schlecht (und die Diskussion war wie man es auf SMP Systemen schnell lösen kann).

Was eure (erik und svenska) Diskussion betrifft, sehe ich es wie erik. Du sagst dem OS wie du es gerne hättest und das OS versucht es so gut es geht umzusetzen.
Kann man mit einem Navi vergleichen. Du willst die schnellste Strecke nehmen und fährst Autobahn, dass Navi weiß aber das auf der Autobahn Stau ist (was du nicht weißt) also wird es dich umleiten, obwohl du eigentlich Autobahn gefahren wärst.

Zitat von: erik
Ein gutes Beispiel ist da die Kryptographie, mancher Algorithmus der vor 20 Jahren noch als absolut unknackbar (selbst mit unbegrenzter Rechenleistung und unbegrenzter Speicherkapazität) angesehen wurde lässt sich heute mit nem simplen programmierbaren Taschenrechner (der auch schon vor 20 Jahren existierte) knacken.
Mal davon abgesehen dass das überall so ist (anderes Bsp. der Mensch wird nie fliegen können, Erde ist Zentrum des Universums, der Mensch wird nie seinen Planeten verlassen usw.), bin ich der Meinung man sollte was solche Sachen betrifft sich nie festlegen. Denn es kann immer neues Wissen hinzukommen und miteinmal ist es doch möglich oder anders.
486
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 13. November 2010, 20:10 »
Zitat von: svenska
Der Grundgedanke, dass RAM*CPU=const bei gegebener Optimierungarbeit gilt, bleibt.
Das kommt halt auf den Algo an. Es gibt Algos die sind schnell, aber haben nen ganz schönen Verschnitt, es gibt Algos die sind nicht so schnell und haben nicht so viel Verschnitt und es gibt inzwischen Algos die sind schnell und haben nicht so viel Verschnitt (und die wären ja deiner Meinung nach nicht möglich).
Um es genauer zu sagen, gibt es halt inzwischen O(1) Implemenationen, die schnell sind und wenig Verschnitt haben.
487
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 13. November 2010, 14:36 »
Zitat von: svenska
QuickSort? Ist ein rekursives Verfahren, für so ziemlich jeden Anwendungsfall optimal. Die Rekursionstiefe hängt vom Sortierzustand der Datenbasis ab.
Ich muss zugeben das ich mich schon eine Weile nicht mehr mit QuickSort beschäftigt habe. Ich bleibe aber dabei das man das weiß und somit einen größeren Stack "beantragen" kann.

Zitat von: svenska
Der Linux-Kernelstack hat übrigens 8 KB.
Meine Kernel-Threads bekommen auch nur 4KB Stack und damit hatte ich bisher keine Problem, aber bei mir wird da ja auch weniger gemacht.

Zitat von: svenska
Da wären wir wieder bei meiner Aussage, dass Speicherverbrauch mal Rechenzeit eine Konstante ist. Du kannst eins gegen das andere eintauschen, musst aber einen Kompromiss finden.
Glaube ich nicht. Denn es wird sich bestimmt irgendwann mal ein intelligenter Algo finden lassen, der alles ganz gut miteinander verreint. Bis dahin ist das natürlich richtig.

Zitat von: svenska
Du optimierst extensiv für minimalen Speicherverbrauch (gcc -Os und entsprechende Algorithmen), Erik optimiert für hohe Ausführungsgeschwindigkeit (gcc -O3 und entsprechende Algorithmen). Beides zusammen geht nicht.
Das stimmt so auch nicht. Also ich optimiere nicht extensiv für einen minimalen Speicherverbrauch, aber ich gehe auch nicht verschwenderisch mit dem Speicher um (ich habe einige Sachen die eher Geschwindigkeit als Speicherverbrauch bevorzugen).
Es gibt sogar nicht wenige Sachen wo ein -Os schnelleren Code erzeugt als einen -O3. Denn das Problem sind die Caches und wenn der Code zu groß wird (und die Caches voll sind und viel nachgeladen werden muss) kann es passieren das kleinerer Code (der "schneller" in die Caches passt) schneller abgearbeitet ist als eigentlich hoch optimierter Code (bestes Bsp. ist das unrollen einer Schleife).
488
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 12. November 2010, 20:06 »
Zitat von: erik
Definiere Bitte "normal"!
Hatte ich doch dahinter geschrieben, eine MMU und keine Segmente, halt FlatMemory mit Paging.

Zitat von: erik
Es soll aber wirklich Probleme geben die sich mit Rekursion am einfachsten und effizientesten lösen lassen.
Ich behaupte mal das man jeden Algo in einen Iterativen Umschreiben kann (ja der Aufwand wird sich bei vielen Sachen wahrscheinlich nicht lohnen) oder man Rekursion iterativ simulieren.
Der eigentliche Punkt ist doch, du weißt wenn du Rekursion nimmst in welche Richtung das geht und wenn du mit 1MB Stack nicht hinkommst dann musst du deinen Code halt anpassen (z.B. in dem du nen Thread erstellst der nen größeren Stack hat).

Zitat von: erik
Das würde ich stark bezweifeln, ein ganz simples malloc hat fast gar keinen Verschnitt außer das es zu jedem Objekt eine feste Anzahl an Bytes für die Verwaltung benötigt.
Das Problem ist, wenn du diese kleinen Anfragen (36Byte) hintereinander machst, ist es viel sinnvoller einmal viel Speicher zu allokieren, machst du die nicht hintereinander, fragmentiert dein Heap irgendwann so stark das du oft irgendwelche 36Byte Löcher hast die du nicht mehr nutzen kannst.
Denn genau das ist doch das Problem bei nem ganz einfachen malloc(), entweder der Speicher ist so fragmentiert das du dir um den Verschnitt keine Sorgen mehr machen musst, weil die Löcher genug Probleme machen oder du hast halt viel Verschnitt (aber nen schnelles malloc()) oder dein malloc() ist zu langsam und skaliert nicht.

Drehen wir den Spieß doch mal um. Hast du denn eine Idee wie man ein malloc() implementieren kann so dass man möglichst wenig Verschnitt hat, möglichst wenig Speicherverbrauch (die Verwaltung) und möglichst schnell ist und skalieren soll das ganz auch noch. Viel Spaß ;)

Edit::

Wenn wir mal deine Slabs mit 512KB nehmen, da passen ja 14563 Objekte mit einer Größe von 36Byte rein und wenn ich jetzt mal den average-case nehme (auch der ist nur einfach so gewählt) wo ich 100 Elemente brauche, dann hast du mit deinen goßen Slabs einen Verschnitt von 99,31% das nenne ich mal Verschwendung ;)

Was ich damit sagen will ist einfach nur, das man sich bei einem Allocator halt auf nen guten Mix aller Nachteile einlassen muss oder man weiß ziemlich genau was für ein Speicherverbrauch das Programm hat und kann dann optimieren.
489
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 12. November 2010, 18:07 »
Zitat von: erik
Nein, ich muss das bestimmt nicht tun, Du musst das tun.
Ahhhh, mit Du meinte ich ein OS auf einer "normalen" Architketur (also keine Segmente und eine MMU) ;)

Zitat von: erik
Und was ist mit Rekursion? Man kann nicht immer zuverlässig vorhersagen wie oft rekursiert wird.
Rekursion habe ich natürlich nicht beachtet, aber ganz ehrlich, bei nem Baum (als Bsp.) werde ich die maximale Rekursionstiefe kennen und wenn ich mal davon ausgehe, das du 4Byte Adresse und 3 Parameter mit jeweils 4Byte und 4 lokale Vriablen mit jeweils 4Byte hast, dann kannst du bei nem Stack von 512KB 16384 Rekursionen durchführen.
Bei so einer Anzahl würde ich dann schon überlegen ob ein anderer Algo nicht performanter ist.

Zitat von: erik
Du willst Deine Slabs nur auf 2er-Potenzen auslegen? Das gibt aber eine fette Speicherverschwendung! Was ist wenn ich 1048576 Objekte mit 36 Bytes brauche, hab ich dann 28MB Verschnitt?
Das ist, so weit ich schonmal Code gesehen habe, die gängige Praxis. Bei deinem Bsp wäre z.B. ein SlabAllocator besser geeignet als ein allgemeines malloc().
Denn ich behaupte mal das du bei dem Bsp. jede malloc() Implementation in den "Wahnsinn" treibst, da wird dein Speicher ordentlich fragmentiert und du wirst auch nen sehr schönen Verschnitt haben.
490
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 12. November 2010, 15:56 »
Zitat von: erik
Ich als Programmierer weiß aber nicht immer wie viel Stack meine Threads so brauchen werden. Gerade bei Workerthreads (die ja oft aus einem vorbestücktem Pool genommen werden) hängt die Stackbenutzung doch sicher auch mal von der konkreten Aufgabe ab die die einzelnen Threads dann tatsächlich bearbeiten.
Du musst die Stacks deiner Threads so oder so beschränken. Denn wenn du mehrere hast, müssen die ja irgendwo hin in deinen Adressraum und somit gibt es dann Grenzen, nämlich da wo ein anderer Thread anfängt.
Da ich als OS nicht wissen kann wieviel Threads ein Programm wohl haben wird, gebe ich dem Programm halt die Möglichkeit die Stack-Größe selber zu wählen.
Was die maximale Größe eines Threads betrifft, die lässt sich rausbekommen. Man muss einfach nur wissen welche Funktionen werden aufgerufen und macht das für jede Funktion die aufgerufen kann wieder (also gucken welche Funktionen werden aufgerufen) und dann bekommst du auch nen maximalen Stackverbrauch.

Ich habe gerade mal geguckt, Standardgröße des Stacks ist unter Windows 1MB und unter Linux 2MB und man kann halt einfach bei der Thread-Erstellung angeben wie groß der Stack sein soll oder man gibt 0 an, dann entscheidet das OS.

Dazu dann die Frage, was ist die "richtige" Stackgröße? Spontan würde ich auch sagen, das 1MB ausreichend ist.

Zitat von: erik
Da dürfte die Suchmaschine Deines geringsten Misstrauens doch sicher behilflich sein.
Ich habe sogar ein eBook zum Speichermanagement unter Linux und auch das konnte es mir nicht näher bringen :(

Zitat von: erik
Wenn der SlabAllocator hinter einem generischen malloc steckt dann muss er für jede übergebene Größe erst mal ermitteln mit welchem Slab-Pool er dann arbeiten soll, wie Aufwändig das ist kann ich jetzt auch nicht so genau sagen.
Sollte gar nicht so schwierig und langsam sein. Man erstellt eh vorher (bei der Initialisierung von malloc()) Slabs mit einer Größe von 2er Potenzen.
Du musst dir ja nur das höchste Bit angucken und in der nächsten 2er Potenz liegt der Spass dann. Dann hast du einfach ein Array und könntest unter x86 sowas machen:
int slot= _bsr(size)
struct slab_t *slab= arrayOfSlabs[slot + 1];
Das sollte verdammt schnell sein, vorallem im Vergleich zu einem malloc() das erst in einer Liste nach einer "perfekten" Größe sucht.

Zitat von: erik
Warum streiten wir uns eigentlich über ein Flag von FlushBurns OS?
Ihr streitet euch wegen mir ;)
491
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 12. November 2010, 08:01 »
Zitat von: erik
Naja, dann wird eben häufiger doch der VMM bemüht neue Slabs herbei zu schaffen.
Eine Möglichkeit das noch etwas weiter zu optimieren, wäre, wenn du dem SlabAllocator beim Erstellen der "Slab-Beschreibung" mitteilst wieviele Objekte du mind. in einem Objekt haben willst.
Denn du als Programmierer solltest ja eher wissen wieviel Objekte du so im Normalfall benötigst.

Würde ich jetzt aber deine Variante benutzen, könnte ich das mit den 8MB RAM für mein OS gleich knicken. Denn mit 512KB pro Objekt-Typ werde ich wohl schon bei über 8MB sein ;)

Zitat von: erik
Das ist aber ein konstruktives Limit in Deinem OS, damit schränkst Du die maximale Anzahl an Threads pro Prozess eventuell erheblich ein (wenn Du die Stacks zu groß machst) oder Deine Threads können sich nicht richtig auf dem Stack austoben (wenn Du diese zu klein machst).
Also mit vorher bekannt meine ich damit, wenn du den Thread erstellst, musst du die max Größe des Threads angeben.

Wie würdest du es denn auf x86 lösen bzw. wie wird es denn gelöst? Wäre nicht schlecht wenn mir mal jemand den Adressraumaufbau unter z.B. Linux erklären könnte, das ich das vielleicht mal verstehe ;)

Zitat von: erik
Wenn Du eine eigene Heap-Library benutzen möchtest dann solltest Du aber auch eine haben die wirklich gut auf das aktuell benutzte OS abgestimmt/optimiert ist.
Das sollte klar sein. Der SlabAllocator wurde ja auch in den UserSpace "übertragen", auf der einen Seite ist das bestimmt von Vorteil, aber auf der anderen Seite, wird wohl kaum ein normales Programm den SlabAllocator direkt nutzen, sondern nur über den Umweg von malloc() und da bringt er (meiner Meinung nach) nicht mehr so viel.
492
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 11. November 2010, 21:23 »
Zitat von: svenska
Du mochtest es nicht, wenn ich libc sage und wirfst mir Linux-Denke vor, also habe ich auf "Library" verallgemeinert. Solange du irgendwann Programme portieren möchtest, wirst du definitiv irgendwelche davon brauchen.
Naja, ich dachte da eher an OS spezifische Libraries wie unter Haiku die Kits und nicht an allgemeine wie libc oder QT und solche Konsorten. Das die API da gleichbleibt ist logisch, aber wenn ich halt so OS spezifische Sachen habe, kann ich das dann auch mit der Library meistens nicht abfangen.

Zitat von: svenska
Ich kann ein paar Benchmarks auf übliche Optimierungen loslassen und eine OS-Weiche einbauen, welche malloc am effizientesten benutzt... oder meine Nutzung auf deine malloc-Implementierung abstimmen. Dein malloc sollte jedenfalls, wenn es schon mit Optimalwerten gefüttert wird, auch optimal arbeiten; und es sollte am besten auf deinen VMM abgestimmt sein.
Ich meine vorallem das du ja nicht statisch linken wirst, sondern die libc als ne shared library nutzen wirst und da kannst du nicht wissen was für eine malloc() Implementation da gerade läuft. Deswegen nutzt du halt deine eigene und die ist direkt in deinem Programm mit drin.
493
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 11. November 2010, 21:04 »
Zitat von: erik
Ich bin ehrlich der Meinung wenn Dein OS mindestens 32 MB will dann geht das völlig in Ordnung. Unter nem Pentium machts doch Dein OS auch nicht.
Ich habe gerade mal damn small linux ausprobiert und das läuft (halbwegs "normal") ab 24MB (waren es glaub ich).
Es ist sogar schwierig für mich mein OS mit nur 4MB zu testen (ist das momentane Minimum) und das geht auch nur in einem Emulator auf richtiger Hardware habe ich dann 8MB und die sind auch das Ziel.
Ich weiß auch gar nicht wo ich im Moment schon bin.

Zitat von: erik
Also ich hab das SlabAllocator-Konzept eher so verstanden das man sich bemüht möglichst große Slabs zu benutzen um eben möglichst selten die normale page-basierte Speicherverwaltung zu belästigen.
Ich hatte mir auch mal direkt den Code angesehen und da war es noch so das sie versucht haben mind.8 Objekte in einen Slab zu bekommen und den Verschnitt unter einer bestimmte Grenze gehalten haben.

Zitat von: erik
Ich möchte für meinem Kernel-Heap die Slabs 512 kBytes groß machen.
Da passen ja von meiner AVL-Struktur 26214 Objekte rein. Aber du bist da ja mit deinen Segmenten auch ein wenig "eingeschränkt" (muss jetzt kein Nachteil sein, jeder hat seine eigenen Ziele).

Zitat von: erik
Schau Dir noch mal dieses Magazin-Zeugs an und überlege wie viele Objekte Du schon allein brauchst um genügend Magazine (wo jedes ja wohl mindestens 8 Objekte aufnimmt) für 8 CPUs zu befüllen. Variable Magazin-Größe möchte ich nicht umsetzen, das ist mir zu viel Aufwand, ich denke eine feste Größe von 16 Objekten pro Magazin ist eine recht gute Basis.
Ich habe dieses Konzept komplett anders implementiert. Bei mir ist ein Magazin immer 4 Objekte groß und jede CPU hat 2 Magazine, ein volles und ein leeres.
Sind beide leer wird eins wieder voll gemacht und sind beide voll wird eins leer gemacht (dafür werden jeweils die "normalen" SlabAllocator Funktionen aufgerufen, es geht von daher an dieser Stelle noch optimaler, aber es läuft erstmal).

Auch die Objekt-Initialisierung findet bei mir nicht statt wenn die Objekte in den Cache/Slab kommen, sondern wenn das Objekt rausgegeben wird (das selbe mit dem Dekonstruktor, da dann wenn das Objekt zurück gegeben wird).
Ich nutze diese Initialisierung im Moment sowieso nur dazu den Speicher des Objekts zu nullen.

Zitat von: erik
Der Heap ist dafür da Objekte mit beliebiger Größe möglichst optimal zu verwalten. Der, mit Pages arbeitende, VMM des OS-Kernels kann das nicht.
Richtig, aber der Heap wird auch nur um ein vielfaches der Page-Größe vergrößert und darum kümmert sich ja malloc().

Zitat von: erik
Wirklich? Bedeutet das wenn ich "new int" mache das ich dann ein komplette Page nur für die 4 Bytes bekomme (und 4092 Byte verschwende)? Was ist wenn ich extrem oft "new int" (oder für andere recht kleine Objekte) mache? Dann entsteht doch ein unheimlicher Verschnitt.
Nope. Wie gesagt ich habe schon ein malloc(), aber eben kein Heap der zusammenhängend ist und nach oben wächst.

Ich habe mit diesem Heap-Konzept so meine Probleme. Eine normale Speicheraufteilung sieht doch so aus, dass der Stack von Oben (oberes Ende des Adressraums) nach unten wächst und der Heap vom Ende des Programm Images nach Oben wächst.
Wo werden dann irgendwelche Libraries hingemappt und was ist wenn man mehrere Threads hat, die ja auch ihre Stacks brauchen und was ist mit den Lücken im Adressraum die ja irgendwann entstehen? Können die dann auch noch benutzt werden oder sind die weg?

Da ich das alles nicht so richtig nachvollziehen kann, habe ich mich dafür entschieden, das der "Heap" halt zerstückelt wird und das bekommt was frei ist. Im Endeffekt wächst alles bei mir nach Oben und auch die Größe des Stacks muss vorher bekannt sein (also der max. Wert).

Zitat von: erik
Also wirklich brauchen tut man das IMHO nicht aber es macht die malloc-Implementierung leichter wenn man den Bereich im virtuellen Adressraum, der für den Heap benutzt wird, einfach so vergrößern kann und der Heap sich nicht über mehrere zusammenhanglose Stücken im virtuellen Adressraum verteilt.
Wieso ist das vorteilhafter? Der Heap wird im Endeffekt doch eh zerstückelt/fragmentiert und du verwaltest den Heap ja auch "nur" in irgendwelchen Datenstrukturen die mit Pointer auf einen bestimmten Speicherbereich zeigen, von daher ist es doch egal ob der zusammenhängend ist oder nicht.

Zitat von: erik
Sowas gibt es in der Standard-libc nicht.
Ich muss wieder lesen üben ;) Habe ich total überlesen das du die libc meinst.

Zitat von: erik
Aha, gut zu wissen, bevor wir später an einander vorbei schreiben. Semaphoren kann es in meinem OS-Kernel nicht geben, weil ununterbrechbar, die gibt es bei mir nur auf User-Mode-Ebene und müssen per Syscall vom Kernel angeboten werden (aber das kommt erst später).
Heißt das auch um die CPU an einen anderen Thread abzugeben, musst du erst wieder zurück in den UserMode oder anders ausgedrückt, du kannst aus deinem Kernel heraus nicht deinen Scheduler aufrufen? Wie machst du es dann das du vom UserMode aus an den Scheduler abgeben kannst ohne das dieser von einem Timer aufgerufen wurde?
494
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 11. November 2010, 17:22 »
Zitat von: erik
Mit 4 bis 8 MB aus zu kommen ist schon ein ziemlich schwieriges Ziel.
Bisher nicht ;) Auch sollte der Speicher für ein Text-Mode OS reichen (was die meisten Hobby OSs ja sind).

Die bei MS müssen das ja auch irgendwie geschafft haben, dann schaffe ich das auch irgendwann ;)

Zitat von: erik
Vor allem ein hochperformanter SlabAllocator dürfte dem nicht gerade zuträglich sein weil er ja möglichst große Slabs will.
Wie kommst du darauf? Ich habe den SlabAllocator so verstanden und implementiert, das er versucht möglichst wenig Verschnitt zu haben und das mind. 8 Objekte in einem Slab drin sind bzw. sind mind. 8 Objekte in einem Slab wird der Slab nicht weiter vergrößert.

Zitat von: erik
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.
Das ist genau der Punkt wo ich am meisten von "normalen" OSs abweiche. Denn was bitte ist ein Heap oder besser was ist an dem anders, als wenn du das OS nach Speicher fragst?

Bei mir gibt es den klassischen Heap nicht, sondern du fragst immer beim OS nach Speicher und bekommst nen Pointer zurück.

Zitat von: erik
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?
Theoretisch möglich wäre es (habe eigentlich schon vor, noch ne Funktion mapAllocAt(uint32t start, uint32t size) zu schreiben), aber ich sehe noch keinen Bedarf dafür.

Kannst du mir denn ein paar (ok, es reicht auch einer) Gründe nennen (die ich nachvollziehen kann bzw. einsehe) warum man sowas unbedingt braucht?

Zitat von: erik
Warum nicht? Kann es nicht mal sein das Du zu einem bereits bestehenden Syscall noch ein Parameter hinzufügen möchtest?
Ich wüsste halt im Moment nicht was sich bei den paar Syscalls ändern sollte, bzw. bis ich soweit bin, das ich wirkliche Anwendungen auf meinem OS laufen habe, sollte die API stabil sein.

Zitat von: erik
Trifft das auch auf Programme zu die nur von der libc (kein POSIX oder sonstwas) abhängig sind?
Warum sollte das da nicht zutreffen. Nehmen wir mal an du hast nen Syscall da irgendetwas macht und du änderst hin dahingehend, das noch ein size-Parameter dazu kommt und den kannst du auch in der Library nicht rausbekommen, sondern den Wert weiß nur der User, wie willst du das wegabstrahieren?

Zitat von: erik
Die Hersteller der besseren Engines kaufen sich eine ordentlich hochperformante malloc-Implementierung (und bleiben in ihrem Code bei malloc).
Also ich persönlich würde ja sowas wie nen SlabAllocator oder wenn es wirklich was bringt für bestimmte Objekte sogar nen eigenen Allocator benutzen.

Zitat von: erik
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.
Ich muss dringend an meinem Ausdruck arbeiten ;)

Mit Lock ist ne Spinlock oder halt ne Read-Write-Lock (was im Endeffekt auch ne Spinlock ist) gemeint, wo du busy-waiting machst und ne Semaphore wirst du als Thread schlafen gelegt und irgendwann wieder aufgeweckt.
Ich habe bisher auch noch keine Semaphore bei mir verwendet und denke auch nicht das ich eine brauchen werde, aber man kann ja nie wissen ;)
495
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 11. November 2010, 15:41 »
Zitat von: svenska
Räumst du nicht auf, wenn ein Task endet/gekillt wird? Weil dann müsstest du alle Pages unmappen und den [physischen] RAM freigeben, der von diesem Task genutzt wurde. Das geht aber nur, wenn das Programm seinen Code eben nicht freigegeben hat (oder es abgefangen wurde).
Doch ich räume auf.

Das Problem welches du ansprichst wird bei mir von meinem Counter abgefangen. Meine vmmMap() erhöht den Counter und meine vmmUnmap() verringert den Counter.
Ist der Counter > 1 (bevor der Counter verringert wurde) dann wird die physische Adresse aus der PageTable gelöscht und kann nicht mehr freigegeben werden.
Ist der Counter = 1 (bevor der Counter verringer wurde) dann wird die physische Adresse in der PageTable stehen gelassen.
Mein Code der dann die ganzen Pages dann an den PMM weitergibt, der guckt ob der Wert in der PageTable ungleich 0 ist und gibt die Page nur dann an den PMM weiter.

Zitat von: svenska
Eher richte ich meine Zugriffe auf malloc() und Freunde so aus, wie das OS sie optimal verarbeitet. Schließlich soll mein App1.0 unter Kernel1.0 lauffähig sein, aber exakt das gleiche Binary auch unter Kernel2.0 ... und das geht nur, wenn ich eine Schicht dazwischen habe, die mir die Unterschiede zwischen Kernel1.0 und Kernel2.0 wegabstrahiert. Das ist üblicherweise die libc/libX11/etc.
Naja, erstmal ist das wieder auf Linux bezogen (und auch noch direkt für X11, das ist nicht wirklich portabel!), für Windows sollte das nicht zutreffen, bzw. ist es ja dort so das nicht alle Programme mit einer neueren Version laufen.
Und warum soll ich das nicht in einer eigenen Library abstrahieren. Der Punkt ist doch das du nie wissen kannst was für ein Allocator hinter malloc() steckt und wie effizient der ist und wenn du deinen eigenen schreibst kannst du alle Sachen die du schon weißt und die für die Speicherverwaltung wichtig sind, mit einfließen lassen und das geht bei malloc() halt nicht.
Aber eigentlich ist das auch egal, weil es nichts zum Thema beiträgt ;) Wir sollten vllt mal eine Multi-Platform Engine angucken um es besser zu wissen.

Zitat von: svenska
Gut, das sind jetzt Details, aber trotzdem könnte eine andere CPU ja auf die gleichen Datenstrukturen zugreifen...
Nein! Jede CPU greift nur auf die Daten zu die zu ihrer CPU ID gehören und das kann ich garantieren weil ich den Code geschrieben habe. Denn wenn du jetzt argumentieren würdest dass das ja anderen Code nicht interessiert, dann gilt das gleiche für Locks. Nur weil du die benutzt müssen die andere nicht auch nutzen.

Zitat von: svenska
Wie reagiert der Kernel aber, wenn diese Speicheranforderung essentiell wichtig war für den Fortbestand des Systems? Da sollte man durchaus Sicherheiten einbauen.
Ich muss dir da schon recht geben, sowas wie nen Sicherheitspuffer sollte man zumindest im Kernel einbauen.
Denn bei mir ist es noch möglich eine relativ "lustige" Situation herbeizuführen. Es kann nämlich passieren das du keinen Speicher mehr freigeben kannst, weil kein Speicher mehr vorhanden ist ;)
496
OS-Design / Re:Adressraum für Kernel und Prozesse
« am: 11. November 2010, 15:27 »
Zitat von: taljeth
Ich widerspreche nur der Behauptung, dass eine Exception immer ein Fehler ist.
Doch ;)

Eine Exception tritt nur auf wenn auch ein Fehler vorliegt (ob das nun ist, weil eine Page nicht vorhanden ist und aus dem Swapp-Speicher geholt werden muss oder eine Division durch 0)!
497
OS-Design / Re:Adressraum für Kernel und Prozesse
« am: 11. November 2010, 13:45 »
Zitat von: taljeth
Exceptions sind nicht grundsätzlich Fehler, die können auch eingeplant sein. Klassisches Beispiel ist der Page Fault beim Swapping.
Swapping habe ich noch nicht, aber recht hast du trotzdem, hatte mal mit dem Gedanken gespielt lazy mapping im Kernel zuzulassen.
Aber Swapping möchte ich im Kernel sowieso nicht haben.

Zitat von: porkchicken
Dass eins falsch war, bekommt man mit einem General Protection Fault mit.
Das ist mir schon klar, aber nen GPF wird ja nicht nur deswegen, sondern auch noch aus anderen Gründen geworfen. Du müsstest also erstmal rausfinden das ein fehlerhaftes Segment Register der Grund war und dann musst du noch unterscheiden ob es einfach "nur" ein Zugriff über Segmentgrenzen hinaus war (ist bei mir bei TLS möglich).

Zitat von: porkchicken
Welches das ist, nur durch den nachfolgenden Einsatz eines Disassemblers.
Wenn man davon ausgeht, das es eh nur ds, es, fs oder gs sein können die falsch sind, dann wäre es doch einfacher, sie entweder mit Standardwerten zu laden oder einfach die 4 zu überprüfen, aber ich glaube nicht das man einen Disassembler dafür bräuchte.

Zitat von: porkchicken
Ich finde eriks Idee immer besser.
Ich bin mir gerade nicht sicher ob du das ironisch oder ernst meinst ;)
498
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 11. November 2010, 13:39 »
Zitat von: svenska
Damit ist es aber für allgemeine Anwendungsfälle nutzlos, sich da einen Kopf drüber zu machen. Außerdem sollte sich ein Userspace-Programm nicht um Alignments kümmern müssen (es sei denn, es geht um Performance oder Ansteuerung einer Hardware), das heißt die API - solltest du sie im Userspace bereitstellen - exponiert hardwareabhängige Dinge und das ist schlecht.
Du und deine libc ;)

Ich behaupte mal das jedes OS einen Syscall hast mit dem du Speicher allokieren kannst und das geht immer nur in vielfachen von PAGE_SIZE. Warum sollte sich auch der Kernel um alles was kleiner ist kümmern? Das macht dein malloc(), das wiederrum nutzt genau solch einen Syscall.

Wenn man nur ein kleines schnelles Programm oder einen eigenen Allocator schreiben will, wird man genau solch einen Syscall nutzen.

Zitat von: erik
Das solltest du tun. Denn tust du es nicht, so stürzt das Programm in der nachfolgenden Anweisung ab (weil der Speicher nicht mehr vorhanden ist) und wenn du dann den Task killst, wird dein Kernel die vorhandenen Ressourcen freigeben wollen, was u.U. zu einem double-free() und damit zu einer Exception/Panic im Kernel führen kann.
Ich sags mal so, wenn das App scheiße baut und seinen eigenen Code freigibt, dann ne Exception bekommt und gekillt wird, wo ist das Problem?
Zu einem double-free() kann es bei mir nicht kommen. Ich hatte auch keine Lust mir ständig nen Kopf darüber zu machen wie oft ne Page gemappt ist und ob ich noch Copy-On-Write machen muss und sowas. Deswegen habe ich für jede Page (physische Adresse) nen Counter, wie oft die gemappt ist und wenn das mehr als 1 ist wird sie nicht freigegeben und wenn der Counter 1 ist dann wird sie erst freigegeben (und ist damit auch aus der PageTable raus).

Zitat von: svenska
Anwendungen sollten niemals die OS-API direkt benutzen, weil sie das inhärent unportabel macht und außerdem dich dazu zwingt, deine Kernel-ABI (nicht nur die API!) stabil zu halten. Sonst funktionieren die Applikationen nicht mehr.
Du solltest anfangen deinen Kopf von den ganzen Linux Sachen zu befreien ;)

Ich hab nen Mikrokernel und da sollte sich die API nun wirklich nicht ändern und wenn sie es doch tut, dann so schlimm das du das auch über Libraries nicht abfangen kannst.

Das sich die API von nem monolithen öfter ändert kann ich nachvollziehen. Denn der bietet ja wesentlich mehr Services an.

Zitat von: svenska
3D-Spiele greifen auch nicht auf den Kernel direkt zu, sondern über Libraries wie OpenGL oder DirectX
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).

Zitat von: svenska
Du solltest die Blockgröße schon von der angeforderten Größe abhängig machen.
Ich befürchte so langsam das entweder du oder ihr beide mich missverstanden haben ;) Denn das ist doch genau das was ich die ganze Zeit sage.
Wenn ich malloc(4) aufrufe und malloc() keinen freien Speicher mehr hat, dann holt sich malloc() nicht 16MB, sondern nur 4KB an Speicher.
Wenn ich aber malloc(128000) aufrufe, dann werden nicht mehrere 4KB Aufrufe gemacht sondern ein Aufruf (an den Kernel) das ich 128KB haben will.

Zitat von: svenska
Geht das bei SMP? Ints ausmachen wirkt doch nur für jede CPU...
Dazu musst du wissen das jede CPU sozusagen ihren eigenen kleinen Cache hat und deswegen reicht es wenn du die Ints ausmachst, denn in dem Moment ist die CPU ja belegt und die anderen CPUs greifen auf ihre kleinen Caches zu. Dadurch kannst du dir das Locking sparen (so fern in diesem kleinen Cache was drin ist).

Zitat von: svenska
Also braucht dein Kernel keinen dynamisch reservierten Speicher
Doch, aber wenn du einen Syscall machst und der Kernel kann keinen Speicher mehr bekommen, dann wird halt ein Fehler zurück gegeben (vergleichbar mit malloc()= NULL).

Zitat von: svenska
Und selbst wenn, dann geht das eben nicht.
Mein reden ;)

Zitat von: svenska
Was passiert, wenn du (weils schnell geht) kein Lock benutzt und während der Arbeit an den Strukturen dein Thread unterbrochen wird - und bei SMP auf einer anderen CPU gleichzeitig an den Strukturen gearbeitet wird? Du solltest Locks lieber möglichst billig machen und an jeder erdenklichen Stelle ein Lock setzen, wo es potentiell krachen kann. Wenn immer nur ein Thread auf ein Lock zugreift [es also unnötig ist, z.B. Singlecore-Systeme], sollte es sogar (fast) schmerzlos sein.
Ich hätte wahrscheinlich noch hinzufügen sollen, 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).
499
OS-Design / Re:Adressraum für Kernel und Prozesse
« am: 11. November 2010, 13:00 »
Zitat von: erik
Aber NMI benutzen, das nenne ich konsequent! Wink
Ich überlege immer nebenher, wie ich diesen NMI wieder loswerden kann ;)

Denn das Problem ist, wie kann ich zw. nem richtigen NMI und ner IPI-Nachricht unterscheiden?

Zitat von: erik
aber gerade bei diesem speziellen Fehler "verbogene Segmentregister" ist es eindeutig das nicht der Kernel sondern ein User-Mode-Prozess gekillt werden muss.
Ich bin gerade zu faul in den Intel Manuals nachzugucken, aber wie bekommt man eigentlich raus das eins (und vorallem welches es dann ist) falsch war?

Eine andere Situation, wäre wenn man bei mir einfach den Wert aus fs (ist fürs TLS) in ds oder es schreibt. Eigentlich müsste man da ja auch ne Exception bekommen, wenn man außerhalb des Segments zugreifen will, oder?
500
Lowlevel-Coding / Re:Allgemeiner Ressourcen-Allocator
« am: 11. November 2010, 12:56 »
Zitat von: erik
aber wen stört das?
Mich ;)

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 ;) ).

Zitat von: erik
In Kaptel 3.5 (auf Seite 7 oben rechts) von http://www.usenix.org/event/usenix01/full_papers/bonwick/bonwick.pdf (ich hoffe mal wir redeten immer vom selben Dokument) ist klar erklärt warum man sich für ein Lock entschieden hat.
Ja wir reden vom selben Dokument.

Blöd nur, das bei mir Locks im Kernel grundsätzlich die Ints ausmachen, Real-Time ist auch kein Hindernis für mich und den letzten Punkt wüsste ich jetzt nicht wie ich ihn umgehen sollte, außer (wie du) grundsätzlich den Kernel nicht unterbrechbar zu machen.

Der Punkt ist aber das die Zeit ein cli und ein sti auszuführen wohl wesentlich kürzer ist, als wenn auf nem Single CPU System ständig die Threads gewechselt werden, weil der Thread der den Lock hält erstmal wieder an die Reihe kommen muss (bzw. müsste ich dann ja auch zw. Single und SMP System unterscheiden, was ich nicht mache und nicht will).

Interessant wird es erst auf nem SMP System. Denn da kann es durchaus passieren das ich ziemlich oft die Ints an und aus machen (in ganz kurzen Abständen). Das könnte dann doch ganz schön Zeit kosten, aber wie gesagt, sollte nicht so viel sein wie die Thread-Wechsel.

Zumal das bei mir die Regel ist, ein Lock (also Ints aus) wird nur da benutzt wo ich Pi mal Daumen sagen, kann das es weniger Zeit benötigt als die Zeit für 3 Thread-Wechsel.
Seiten: 1 ... 23 24 [25] 26 27 ... 43

Einloggen