Autor Thema: Funktionsaufruf Kernel -> Modul  (Gelesen 29743 mal)

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #60 am: 30. August 2010, 10:21 »
Hallo,


Zitat von: erik
Bei einem Monolithischen Kernel sieht der Kernel alles von der Applikation da ist mein Konzept schon mal ein echter Fortschritt.
Ähm, der Kernel sieht immer alles von der Applikation. Was genau meinst du in dem Fall?
Ich meine, das wenn wir einen OS-Kernel als potentiell fehlerhaft betrachten, so wie absolut jede Software, dann hat ein Micro-Kernel den Vorteil das er deutlich kleiner ist und damit (hoffentlich) weniger Fehler enthält. Ein gut desingter Micro-Kernel hat nicht mal ein tausendstel der Größe eine dicken Monolithen (z.B. Linux) und da viele Fehler erst durch Wechselwirkungen entstehen sollte er deutlich weniger als ein tausendstel der Fehler enthalten. Fehler in einem OS-Kernel sind besonders schlimm weil sie potentiell das gesamt System beeinflussen können, genau deshalb hat man sich ja das Konzept der Micro-Kernel erdacht. Viele der OS-Funktionalitäten liegen bei einem Micro-Kernel-OS in normalen User-Mode-Prozessen (der Personality) und enthaltene Fehler können sich damit nicht so auswirken wie bei einem monolithischen Kernel. Der VFS-Code in einem Monolithen kann prinzipiell eine komplette Applikation beeinflussen, bei einem Micro-Kernel mit meinem IPC-Konzept nur die Speicherbereiche die die Applikation explizit dem VFS zur Verfügung stellt. Bei meinem Konzept besteht noch das Risiko das in den Rand-Bereichen der Speicher-Bereiche Schaden angerichtet werden könnte, das ist eben der Preis wenn man auf das Kopieren komplett verzichten möchte. Ich habe mir daher noch mal meine Segment-Descriptoren angesehen und denke das ich das Alignment problemlos auf 16 Byte reduzieren kann. Ich denke in den übrigen maximal 15 Bytes dürfte das Schadenspotential extrem gering sein und auf einer richtigen 64Bit-RISC-CPU sind alle Datenstrukturen passend ausgerichtet so das diese Rand-Bytes mit hoher Wahrscheinlichkeit eh unbenutzt sind. Auch die Pointer die malloc liefert sind wohl immer mindestens auf 16 Bytes ausgerichtet. Wie seht ihr das Risiko mit diesen kleinen Rand-Bereichen?
Zusätzlich bieten meine Segmente den Vorteil das ich das Lesen und Schreiben unabhängig von einander freischalten kann, so das ein Service auf die Request-Speicher-Bereiche nur Lesend und auf die Response-Speicher-Bereiche nur Schreibend zugreifen kann.

Was ist wenn der Empfänger jetzt in den Buffer schreiben will? Muss er dann kopieren oder darf er in das Segment schreiben?
Dort wo der Service seine Antwort oder eingelesene Nutzdaten ablegen soll darf er natürlich Schreiben (aber nicht Lesen). In den Segmenten wo der Request oder die zu schreibenden Nutzdaten liegen darf der Service natürlich nur Lesen (aber nicht Schreiben). Kopiert werden muss erst mal gar nichts.

Damit (wenn er in das Segment schreiben darf) gibt es dann 2 Probleme, 1. kann er dann im ungünstigsten Fall Daten beim Empfänger ändern und der Sender kann mit den Daten in dem Segment praktisch nichts mehr anfangen, da sie ja nicht mehr dem entsprechen was er mal gesendet hat.
Ich verstehe nicht was Du meinst! Du scheinst das Wort "er" in verschiedenen Bedeutungen zu nutzen.
Der Client kann beim Service weder etwas verändern noch etwas lesen, er gibt ja seine Speicher-Bereiche für den Service frei und nicht umgekehrt. (Ich hoffe das war es was Du wissen wolltest, wenn nicht dann formuliere Deine Frage Bitte noch mal neu)

Das letzte Problem ist besonders fürs VFS entscheidend. Denn du willst ja das Kopieren vermeiden, wenn der Empfänger aber die Daten ändern darf, dann kannst du sie nicht mehr einfach an jeden Clienten senden (der die Datei lesen möchte), da sie nicht unbedingt dem entsprechen muss was eigentlich in der Datei steht.
Darf der Empfänger nicht in das Segment schreiben, musst du ja doch wieder kopieren, damit er das machen kann.

Also sparst du im Endeffekt 1 Kopiervorgang (aber auch das wären im "schlimmsten" Fall 50% Ersparnis).
Also hier verstehe ich gar nichts mehr. Sorry, aber Bitte formuliere Deine Frage noch mal neu.
Ein Lesezugriff auf den Cache im VFS läuft immer auf einen Kopiervorgang hinaus (vom Cache in den Buffer der Applikation), weil der Service (in diesem Fall das VFS) ja keine Speicherbereiche an den Client geben kann (wäre auch irgendwie doof).


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #61 am: 30. August 2010, 10:42 »
Zitat von: erik
Wie seht ihr das Risiko mit diesen kleinen Rand-Bereichen?
Naja, ist halt so ne Sache ;) Ich sag mal wenn du sowas zulässt, dann kannst du auch sagen, das du die Segmente gar nicht brauchst und kannst alles über Paging machen (weil da hast du ja auch nur "kleine" Randbereiche).
Ich würde halt sagen, wenn dann richtig. Obwohl das mit den Segmenten natürlich auch nur Sinn macht, wenn kein Paging dahinter steckt, weil ansonsten könntest du ja auch fast alles übers Paging machen, bzw. könntest du auf x86 theoretisch auch solche Einblendungen per Paging machen und dann ein Segment drüber legen, damit nicht auf die Randbereiche zugegriffen werden kann. Dies heißt dann aber auch, das der ganze restliche Speicher auch über Segmente gemacht werden muss und genau da sehe ich halt auch das Problem.
Der Aufwand dafür wäre (mir) zu groß. Weil du speicherst dann neben dem Pointer auch noch das Segment wo der Poiter drin liegt.

Zitat von: erik
Ich verstehe nicht was Du meinst! Du scheinst das Wort "er" in verschiedenen Bedeutungen zu nutzen.
Der Client kann beim Service weder etwas verändern noch etwas lesen, er gibt ja seine Speicher-Bereiche für den Service frei und nicht umgekehrt. (Ich hoffe das war es was Du wissen wolltest, wenn nicht dann formuliere Deine Frage Bitte noch mal neu)
Ich seh gerade, dass ich mich da wirklich sehr dumm ausgedrückt habe.

Also was ich meine ist, das man ja im Normalfall eine Nachricht abholt und dieser Speicher wo die Nachricht drin ist, ist dann meiner und ich kann machen was ich will. Mir fällt gerade kein Bsp dafür ein, aber was ist wenn du die Nachricht nicht nur liest, sondern vielleicht auch noch ein wenig veränderst um dann damit zu arbeiten?
Das würde bei dir dann heißen, dass du die Daten doch wieder kopieren musst und um mal bei dem Bsp mit der 300MB Datei zu bleiben, könnte das im Extrem Fall heißen, dass du die 300MB zum Lesen und nochmal 300MB zum Schreiben brauchst.
Wo sich mir dann auch die Frage stellt, wie lange ist das Segment gültig oder musst du es als Empfänger dann wieder selbst freigeben? Oder was passiert wenn der Sender das Segment freigibt, aber der Empfänger noch damit arbeiten will?

Zitat von: erik
Also hier verstehe ich gar nichts mehr. Sorry, aber Bitte formuliere Deine Frage noch mal neu.
Ein Lesezugriff auf den Cache im VFS läuft immer auf einen Kopiervorgang hinaus (vom Cache in den Buffer der Applikation), weil der Service (in diesem Fall das VFS) ja keine Speicherbereiche an den Client geben kann (wäre auch irgendwie doof).
Du hast mir die Frage schon beantwortet (man darf in die erhaltenen Daten nicht schreiben).

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #62 am: 30. August 2010, 12:38 »
Hallo,


Zitat von: erik
Wie seht ihr das Risiko mit diesen kleinen Rand-Bereichen?
Naja, ist halt so ne Sache ;) Ich sag mal wenn du sowas zulässt, dann kannst du auch sagen, das du die Segmente gar nicht brauchst und kannst alles über Paging machen (weil da hast du ja auch nur "kleine" Randbereiche).
Beim Paging sind diese Randbereiche aber deutlich größer und damit wirklich ein ernsthaftes Risiko.

Obwohl das mit den Segmenten natürlich auch nur Sinn macht, wenn kein Paging dahinter steckt
Genau das ist das Ziel das ich mit den Segmenten verfolge, ich möchte das langsame und speicherkostende Paging los werden.

Der Aufwand dafür wäre (mir) zu groß. Weil du speicherst dann neben dem Pointer auch noch das Segment wo der Poiter drin liegt.
Ein Pointer besteht bei mir aus 2 Teilen, dem Selector und dem Offset, und ist damit schon etwas größer als ein Pointer in einem Flat-Memory-System, dafür kann ich an etlichen anderen Stellen einsparen. Ich denke die Segmentierung wird sich auch für die Performance lohnen.

Also was ich meine ist, das man ja im Normalfall eine Nachricht abholt und dieser Speicher wo die Nachricht drin ist, ist dann meiner und ich kann machen was ich will.
Auf welches IPC-Konzept bezieht sich diese Frage? Ich gehe nicht davon aus das Du mein IPC-Konzept meinst denn bei mir wird nichts "abgeholt"!

aber was ist wenn du die Nachricht nicht nur liest, sondern vielleicht auch noch ein wenig veränderst um dann damit zu arbeiten?
Wenn der Service den Request, den er vom Client bekommen hat, erst modifiziert und dann abarbeitet ist das sein Problem. Das muss er beim meinem IPC-Konzept auf jeden Fall in eigenem Speicher machen (also vorher kopieren) den Requests werden dem Service nur ReadOnly übergeben.

Das würde bei dir dann heißen, dass du die Daten doch wieder kopieren musst und um mal bei dem Bsp mit der 300MB Datei zu bleiben, könnte das im Extrem Fall heißen, dass du die 300MB zum Lesen und nochmal 300MB zum Schreiben brauchst.
Wovon schreibst Du da? Lesen und Schreiben (also fread und fwrite) sind bei mir 2 verschiedene/unabhängige IPC-Vorgänge.

Wo sich mir dann auch die Frage stellt, wie lange ist das Segment gültig oder musst du es als Empfänger dann wieder selbst freigeben? Oder was passiert wenn der Sender das Segment freigibt, aber der Empfänger noch damit arbeiten will?
Ich denke mein Kernel wird das freigeben von Segmenten aus denen Teile vererbt wurden verhindern müssen und einen passenden Error-Code zurück geben oder das Segment wird als gelöscht markiert und wenn es keine Vererbungen (quasi Links) mehr darauf gibt kann es endgültig gelöscht werden.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #63 am: 30. August 2010, 12:55 »
Zitat von: erik
Auf welches IPC-Konzept bezieht sich diese Frage? Ich gehe nicht davon aus das Du mein IPC-Konzept meinst denn bei mir wird nichts "abgeholt"!
Gut dann bekommst du halt eine Nachricht, aber das was ich meine bleibt gleich.

Zitat von: erik
Wovon schreibst Du da? Lesen und Schreiben (also fread und fwrite) sind bei mir 2 verschiedene/unabhängige IPC-Vorgänge.
Mir geht es darum, dass du die Daten ja anforderst, weil du damit arbeiten willst und wenn wir bei unserem Bsp bleiben, dann hast du die ganze 300MB Datei geladen (bzw. als Segment in deinem Prozess) und willst jetzt die Datei anbestimmten Stellen bearbeiten (das können viele, aber auch nur ein paar sein) und dann stehst du vor der Wahl, machst du für jede kleine Änderung einen neuen IPC Aufruf oder änderst du alles mit einmal und sagst dann das du die Datei speichern willst.
In dem Fall müsstest du die ganzen 300MB in deinen eigenen (ich meine mit deinen, den vom Clienten) Speicher kopieren und dann ändern.
Den Speicher (mit den geänderten Daten) willst du (als Client) jetzt aber auch behalten, weil du damit noch weiter arbeiten willst.

Zitat von: erik
Beim Paging sind diese Randbereiche aber deutlich größer und damit wirklich ein ernsthaftes Risiko.
Der Punkt ist aber, dass das nur "halbherzig" ist. Wirklich sicher ist es nicht.
Wer sagt, dass nicht genau diese 16bytes den Server (Service) abstürzen lassen bzw. das dieser dann mit falschen Daten arbeitet?! Ist dann ähnlich einem Bufferoverflow.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #64 am: 30. August 2010, 14:35 »
Beim Paging sind diese Randbereiche aber deutlich größer und damit wirklich ein ernsthaftes Risiko.
Das ist Blödsinn, erik, und das weißt du auch. Entweder es ist dir hochoffiziell egal, dass Prozesse auf Daten zugreifen können, die nicht für sie bestimmt sind (ob lesend oder schreibend macht dabei wieder keinen Unterschied, Lesen ist bei sensiblen Daten schlimm genug), oder es ist dir nicht egal. Ob das Fenster für Leaks kleiner oder größer ist, spielt keine Rolle. Kaputt ist kaputt.

Bevor ich sowas mache, würde ich einfach sagen, wer fwrite() benutzt, ist selber schuld. Wenn er Performance will, soll er ein natives erikos_write() benutzen, das ein Alignment erfordert.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #65 am: 30. August 2010, 20:08 »
Hallo,


Gut dann bekommst du halt eine Nachricht
Richtig, in meiner Welt kommt der Postbote zu mir und bringt das Paket.

aber das was ich meine bleibt gleich.
Das kann ich wirklich nicht beurteilen weil ich echte keine Ahnung hab was Du eigentlich meinst.

Mir geht es darum, dass du die Daten ja anforderst, weil du damit arbeiten willst und wenn wir bei unserem Bsp bleiben, dann hast du die ganze 300MB Datei geladen (bzw. als Segment in deinem Prozess) und willst jetzt die Datei anbestimmten Stellen bearbeiten (das können viele, aber auch nur ein paar sein) und dann stehst du vor der Wahl, machst du für jede kleine Änderung einen neuen IPC Aufruf oder änderst du alles mit einmal und sagst dann das du die Datei speichern willst.
In dem Fall müsstest du die ganzen 300MB in deinen eigenen (ich meine mit deinen, den vom Clienten) Speicher kopieren und dann ändern.
Den Speicher (mit den geänderten Daten) willst du (als Client) jetzt aber auch behalten, weil du damit noch weiter arbeiten willst.
Ich glaube Du hast noch nicht verstanden wie mein Konzept arbeitet.
Bei mir muss der Client den Speicher schon haben, ob das ein statisches Array ist oder per malloc kreiert wurde ist egal, um dann (per IPC) einen Service aufzufordern dort etwas hinein zu legen. Am Buffet musst Du Deinen Teller schon mitbringen damit Dir die Bedienung was drauf tut. Ein Client kann also per malloc ein 300MByte-Array erstellen, danach dem VFS-Service sagen er soll dort den Inhalt einer Datei hinein packen (ob der VFS-Service das aus seinem privaten File-Cache kopiert oder einem File-System-Treiber sagt das dieser einem Block-Device-Treiber sagt er soll die richtigen Sektoren dort ablegen lassen ist für den Client egal und auch nicht sichtbar), dann kann der Client in seinem Speicher rummachen wie er will (in dieser Zeit gehört sein Speicher nur ihm) und als letztes kann er dem VFS-Service wieder sagen das dieser die Daten aus dem Array abspeichern soll (auch hier ist es wieder egal ob der VFS die Daten nur in seinen Cache kopiert oder an ein Datei-System zum abspeichern auf HDD weitergibt). Für die 2 IPC-Aktionen (fread und fwrite) wird dem VFS-Service temporär Zugriff auf diesen Speicher-Bereich des Clients gestattet (und der VFS kann das auch seinerseits weiterreichen, also einem untergeordnetem Service wiederum Zugriff gewähren), sonst nicht.

Wer sagt, dass nicht genau diese 16bytes den Server (Service) abstürzen lassen bzw. das dieser dann mit falschen Daten arbeitet?! Ist dann ähnlich einem Bufferoverflow.
Mal davon abgesehen das der Service den Client abstürzen lassen könnte (weil ja der Service auf den Speicher des Clients zugreifen darf) hast Du natürlich recht.


Das ist Blödsinn, erik, und das weißt du auch. [.....] Kaputt ist kaputt.
Danke für Deine ehrlichen Worte. Mein Problem ist das die Bits in den Descriptoren begrenzt sind. Wenn ich mehr Bits am unteren Ende vom Limit brauche gehen die oben verloren also die maximal mögliche Segmentgröße wird weniger (das gleiche Problem ist auch beim Minimum).
In der 64 Bit-Variante meiner CPU habe ich fürs Limit einen 28 Bit-Wert und einen Shift-Faktor mit 4 Bit (alle geraden Werte von 0 bis 30). Damit kann ich z.B. eine Segmentgröße von 2^58 Bytes darstellen aber eben nur mit einer Genauigkeit von 2^30 Bytes (wer so riesige Segmente braucht bekommt die nur noch in Schritten zu 1 GByte), ich kann damit aber auch ein Segment bis zu 256 MBytes auf das Byte genau darstellen. Bei der Variante mit den 16 Bytes Genauigkeit wären immerhin Segmente bis 4 GBytes möglich. Hier wäre es vermutlich am geschicktesten wenn man diese Regeln ganz klar darlegt und der Client kann dann entscheiden ob ihm 256 MBytes pro IPC-Vorgang genug sind oder er für etwas mehr Performance ein ganz klein wenig die Hosen runter lässt.
Bei der 32 Bit-Variante meiner CPU sind die Descriptoren etwas anders aufgebaut, da kann ich immer die nötigen Bits haben um das Limit und das Minimum aufs Byte genau fest zulegen.

Bevor ich sowas mache, würde ich einfach sagen, wer fwrite() benutzt, ist selber schuld. Wenn er Performance will, soll er ein natives erikos_write() benutzen, das ein Alignment erfordert.
Man könnte auch einfach sagen das sich die Performance von allein einstellt wenn die Daten ein entsprechendes Alignment vorweisen, das wäre mir zumindest lieber.

Was hältst Du von der Variante:
Wenn man dem fread/fwrite (per define o.ä.) sagt wie viel Risiko es eingehen darf (also wie groß die Lücke maximal sein darf, was auch 0 sein kann) dann kann es klar entscheiden (anhand der Größe und des Alignments des übergebenen Speicherbereichs) ob es mehrere IPC-Vorgänge benötigt. Wenn z.B. ein Speicherbereich mit 4 GBytes (also ein vielfaches von 16) mit einem Alignment von 16 Bytes gegeben ist dann reicht ein IPC-Vorgang, wenn die Daten aber nur auf 4 Bytes genau ausgerichtet sind dann müssen auch 4 IPC-Vorgänge benutzt werden wenn keine Lücke entstehen darf und wenn 4 Byte Lücke erlaubt sind dann reichen doch wieder 2 IPC-Vorgänge (mit 8 Byte Alignment). Ich denke das lässt sich in sehr wenige Zeilen C-Code gießen und sollte immer das Optimum an Performance, bei Einhaltung des gegeben Sicherheitsbedürfnis, erreichen.
Ist das Okay?


Grüße
Erik
« Letzte Änderung: 30. August 2010, 20:10 von erik.vikinger »
Reality is that which, when you stop believing in it, doesn't go away.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #66 am: 30. August 2010, 20:35 »
Danke für Deine ehrlichen Worte. Mein Problem ist das die Bits in den Descriptoren begrenzt sind. Wenn ich mehr Bits am unteren Ende vom Limit brauche gehen die oben verloren also die maximal mögliche Segmentgröße wird weniger (das gleiche Problem ist auch beim Minimum).
Das kann ich schon nachvollziehen. Aber wenn man zwei Probleme hat, ist es keine gute Idee, das erste so zu lösen, dass das zweite zwangsläufig ungelöst bleibt.

Ich glaube, du könntest sogar ein paar Gründe finden, warum es nicht schlimm ist, wenn der andere Prozess Zugriff hat. Oder zumindest unter bestimmten Bedingungen, z.B. wenn der Zielprozess höher privilegiert ist. Aber "es sind doch nur 12 Bytes" ist sicher keine solche Begründung, sondern maximal eine faule Ausrede. Und das ist es, was ich meinte, dass dir sicher auch selbst bewusst ist.

Zitat
Bevor ich sowas mache, würde ich einfach sagen, wer fwrite() benutzt, ist selber schuld. Wenn er Performance will, soll er ein natives erikos_write() benutzen, das ein Alignment erfordert.
Man könnte auch einfach sagen das sich die Performance von allein einstellt wenn die Daten ein entsprechendes Alignment vorweisen, das wäre mir zumindest lieber.
Ich hab es lieber, wenn mir das OS auf die Finger klopft als dass es heimlich, still und leise meine Performance kaputtmacht, ohne mir was davon zu sagen. Aber das ist Geschmackssache.

Zitat
Wenn man dem fread/fwrite (per define o.ä.) sagt wie viel Risiko es eingehen darf (also wie groß die Lücke maximal sein darf, was auch 0 sein kann)
Nein. Das ist eine boolesche Entscheidung. Entweder sicher oder unsicher. Zwischen 16 und 1024 ist kein wesentlicher Unterschied mehr, nur 0 oder nicht 0 sind entscheidend.

Dass du je nach Situation das eine oder das andere wählst, wäre aus meiner Sicht vertretbar.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #67 am: 30. August 2010, 20:53 »
Zitat von: erik
Das kann ich wirklich nicht beurteilen weil ich echte keine Ahnung hab was Du eigentlich meinst.
Das könnte daran liegen das ich noch immer nicht dein Konzept mit den Segmenten vollständig verstanden habe, bzw. mir nicht klar ist wie du bestimmte Probleme lösen willst. Aber so langsam (hoffe ich) verstehe ich es.

Was machst du eigentlich wenn dir die Segmente ausgehen und du aber noch freien virtuellen Speicher hast? Was ich mir auch nicht so richtig vorstellen kann, wie löst du das mit dem Auslagern der Daten?

Ich sage mal (vielleicht auch aus Gewohnheit) das wenn du die Segmente auch auf 4kb Einheiten festlegen würdest, dass dann viele Sachen einfacher werden, aber dann wären sie natürlich auch wieder sinnlos ;)

Im Endeffekt, habe ich bei mir schon Caching drin (da die Daten immer vom VFS Service in den Clienten kopiert werden) und du müsstest da halt genauso kopieren. Du würdest dir also einmal kopieren (bei mir aus der Pipe in den Buffer des Clienten) ersparen.
Aber wenn ich dein Konzept so übernehmen würde, dann bräuchte ich einfach zu sagen, dass ich in dem Fall was ähnliches mache und einfach den Bereich der zu lesen ist (bzw. halt die 4kb Pages wo der Bereich drin liegt) einblendet (natürlich read-only) und dann die Daten von da aus in den Buffer des Clienten kopiere, so würde ich auch auf einmal kopieren kommen.
Die Idee ansich ist zwar gut, hat aber das Problem (was eher selten bis gar nicht auftauchen sollte) wenn mir der virtuelle Speicher ausgeht, funktioniert das ganze nicht mehr, da sind dann meine 4kb Pipe´s wieder von Vorteil.

Edit::

Für das Problem das mir der virtuelle Speicher ausgehen sollte, werden halt immer nur 4kb eingeblendet und ich kopiere die Daten dann von da aus in den Buffer.

Ich denke ich werde das Konzept so nehmen, es sein denn ihr findet Probleme damit.
« Letzte Änderung: 30. August 2010, 20:56 von FlashBurn »

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #68 am: 30. August 2010, 21:20 »
Hallo,


Aber wenn man zwei Probleme hat, ist es keine gute Idee, das erste so zu lösen, dass das zweite zwangsläufig ungelöst bleibt.
Auch wieder ein gutes Argument. Gut das ich gefragt hab.

Ich hab es lieber, wenn mir das OS auf die Finger klopft als dass es heimlich, still und leise meine Performance kaputtmacht, ohne mir was davon zu sagen. Aber das ist Geschmackssache.
Wieso, es gibt Dir heimlich, still und leise mehr Performance wenn Du Dich zufällig (oder auch absichtlich) an die Alignment-Vorgaben hältst. Aber da sind wir wohl mal wieder beim Haare-Spalten.

Nein. Das ist eine boolesche Entscheidung. ...
Okay, also entweder fread/fwrite dürfen mit voller Performance laufen und scheren sich nicht um die Sicherheit oder sie müssen genau aufpassen wie viel Performance sie benutzen können ohne die Sicherheit zu gefährden. Wie schon gesagt, ich denke das lässt sich sehr simpel implementieren.

Dass du je nach Situation das eine oder das andere wählst, wäre aus meiner Sicht vertretbar.
Dann sind wir uns ja einig. :)


Das könnte daran liegen das ich noch immer nicht dein Konzept mit den Segmenten vollständig verstanden habe, bzw. mir nicht klar ist wie du bestimmte Probleme lösen willst. Aber so langsam (hoffe ich) verstehe ich es.
Achte nicht zu sehr auf meine Segmente, die machen zwar ein paar Dinge ganz einfach aber sind keine zwingende Voraussetzung für mein IPC-Konzept.

Was machst du eigentlich wenn dir die Segmente ausgehen und du aber noch freien virtuellen Speicher hast?
Pro LDT sind 32768 Segmente möglich (jeder Prozess hat seine eigene LDT), das sollte für ne Weile reichen und wenn die doch mal knapp werden dann geht eben der IPC-Vorgang gerade nicht und wird gequeued (also der Client blockiert).

Was ich mir auch nicht so richtig vorstellen kann, wie löst du das mit dem Auslagern der Daten?
Per Paging, siehe dazu in den Thread mit der eigenen CPU, da diskutieren Svenska und ich recht ausführlich darüber.

Ich sage mal (vielleicht auch aus Gewohnheit) das wenn du die Segmente auch auf 4kb Einheiten festlegen würdest, dass dann viele Sachen einfacher werden, aber dann wären sie natürlich auch wieder sinnlos ;)
Die Segmente sind auch auf 4 kBytes festgelegt, es gibt nur bei jedem Segment ein Minimum und ein Limit. Das bedeutet die Offsets fangen nicht immer bei 0 an. Für den Speicher-Manager vom Kernel belegen die Segmente immer ganze Pages, sonst wäre das auch zu kompliziert. Den dadurch entstehenden Verschnitt hast Du ja bei Flat-Memory-System ganz genau so.

Im Endeffekt, habe ich bei mir schon Caching drin (da die Daten immer vom VFS Service in den Clienten kopiert werden) und du müsstest da halt genauso kopieren. Du würdest dir also einmal kopieren (bei mir aus der Pipe in den Buffer des Clienten) ersparen.
Ja, wenn im VFS ein Cache vorhanden ist dann bedeutet das immer kopieren, aber der HDD-Treiber könnte direkt in den Cache vom VFS reinschreiben (lassen) obwohl noch der Datei-System-Treiber dazwischen hängt (also Zero-Copy von der HDD bis in den VFS-Cache).

Aber wenn ich dein Konzept so übernehmen würde, dann bräuchte ich einfach zu sagen, dass ich in dem Fall was ähnliches mache und einfach den Bereich der zu lesen ist (bzw. halt die 4kb Pages wo der Bereich drin liegt) einblendet (natürlich read-only) und dann die Daten von da aus in den Buffer des Clienten kopiere, so würde ich auch auf einmal kopieren kommen.
Hä, wer gibt hier an wen Speicher weiter?

Die Idee ansich ist zwar gut
Das möchte ich aber auch meinen, bin ich schließlich fast von alleine drauf gekommen (mal davon abgesehen das taljeth mich in diese Richtung gestoßen hat und die Schriften des Tanenbaum halfen dann das etwas zu verfeinern). :-D

hat aber das Problem (was eher selten bis gar nicht auftauchen sollte) wenn mir der virtuelle Speicher ausgeht, funktioniert das ganze nicht mehr
Spätestens auf einer 64 Bit-Plattform ist dieses Problem erst mal für absehbare Zeit in weiter Ferne.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #69 am: 30. August 2010, 21:32 »
Ich denke ich werde das Konzept so nehmen, es sein denn ihr findet Probleme damit.
Wenn wir da Probleme finden sollen dann musst Du Dein Konzept schon mal konkret vorstellen. ;)
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #70 am: 30. August 2010, 21:39 »
Zitat von: erik
Achte nicht zu sehr auf meine Segmente, die machen zwar ein paar Dinge ganz einfach aber sind keine zwingende Voraussetzung für mein IPC-Konzept.
Und genau da muss ich dir wiedersprechen (bzw. habe bestimmt noch nicht alles verstanden) ;)

Wie funktioniert denn dein malloc? Das Problem was ich habe, wenn wir die 300MB Datei nehmen, dann wäre es ja möglich das dir malloc nen Speicherbereich zurückgibt der nicht an 4kb ausgerichtet ist (sehr unwahrscheinlich, aber möglich). Wie würdest du das dann mit deinen Segmenten lösen? Und mit reinem Paging kannst du dann nicht einfach sagen, ich blende dann mal in den 300MB Buffer meinen (den vom Service) Speicher ein!

Zitat von: erik
Pro LDT sind 32768 Segmente möglich (jeder Prozess hat seine eigene LDT), das sollte für ne Weile reichen und wenn die doch mal knapp werden dann geht eben der IPC-Vorgang gerade nicht und wird gequeued (also der Client blockiert).
Dazu wäre es auch gut, wenn du mal erklärst wie dein malloc funktionieren soll oder besser wann ein neues Segment erstellt wird und wann nicht.

Zitat von: erik
Hä, wer gibt hier an wen Speicher weiter?
Also fread würde einfach zum Service sagen, gib mir mal den Speicher von da bis da (den Bereich wo die zu lesenden Daten drin sind) und der Service gibt dann als Antwort ne ID für SharedMem zurück die in den Clienten eingeblendet wird und fread kann aus diesem "Cache" dann in den Buffer des Clienten kopieren.

Zitat von: erik
Spätestens auf einer 64 Bit-Plattform ist dieses Problem erst mal für absehbare Zeit in weiter Ferne.
Ich habe mir schon überlegt immer nur 4kb einzublenden, zu kopieren und die nächsten 4kn einblenden zu lassen.
Einziges Problem mit dem Caching ist, was passiert wenn dem Storage-Server der virtuelle Speicher ausgeht und noch eine Datei geöffnet werden soll?

Leider habe ich nicht vor so schnell mein OS auf eine 64bit Architektur zu portieren bzw. neuzuschreiben.

Zitat von: erik
Wenn wir da Probleme finden sollen dann musst Du Dein Konzept schon mal konkret vorstellen. Wink
Ich hoffe die obige Beschreibung reicht?!

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #71 am: 31. August 2010, 20:21 »
Hallo,


Wie funktioniert denn dein malloc?
Ich wollte den Heap über mehrere Segmente verteilen, eventuell sogar für jede angefragte Objekt-Größe ein eigenes Segment oder zumindest etwas in dieser Richtung. Genau weiß ich das noch nicht. Es wird auf jeden Fall nicht für jeden Aufruf von malloc ein neues Segment erstellt, da wären die Segmente ziemlich schnell alle und der Verschnitt wäre riesig (weil ein Segment immer ganze Pages belegt). Vielmehr möchte ich das gleichgroße Objekte alle im selben Segment drin sind und wie ein Array verwaltet werden. Der Vorteil meiner Segmente ist das ich die einzelnen Segmente unabhängig voneinander Vergrößern und auch wieder Verkleinern kann, ich hab nicht nur einen virtuellen Adressraum, wo man schon mal mit Konflikten rechnen muss, sondern ziemlich viele die eben völlig unabhängig voneinander sind.

Das Problem was ich habe, wenn wir die 300MB Datei nehmen, dann wäre es ja möglich das dir malloc nen Speicherbereich zurückgibt der nicht an 4kb ausgerichtet ist (sehr unwahrscheinlich, aber möglich). Wie würdest du das dann mit deinen Segmenten lösen?
Mit meinen Segmenten kann ich recht flexibel auch unausgerichteten Speicher beschreiben, so ein Segment hat nicht nur eine Basisadresse (die immer auf die kleinste Page-Größe ausgerichtet sein muss) sondern auch ein Minimum (gültige Offsets müssen größer oder gleich sein) und ein Limit (gültige Offsets müssen kleiner oder gleich sein). Wenn die 300 MBytes mitten in einem Segment drin liegen (z.B. an 0x123456) dann wird das Offset auf die nächste Page-Grenze abgerundet (also auf 0x123000) und dort die Basisadresse der erbenden Segments hin gelegt (die Basisadresse muss sich natürlich auf den echten linearen Speicher beziehen und ist daher nicht 0x123000 sondern 0x123000 + Basis vom beerbten Segments), die restliche Distanz (0x000456) ist dann das Minimum im neuen Segment und das Limit ist dann das Ende der Daten (also 0x000456 + Datengröße). Ich hoffe das war einigermaßen verständlich. Es ist jedenfalls nur ein kurze Prozedur ein neues Segment für das Memory-Sharing für IPC zu erstellen, deswegen hoffe ich das mein IPC kaum teurer ist als auf anderen Plattformen ein Syscall.

Und mit reinem Paging kannst du dann nicht einfach sagen, ich blende dann mal in den 300MB Buffer meinen (den vom Service) Speicher ein!
Wenn man beim Paging mit unausgerichteten Daten konfrontiert wird dann muss eben die erste und letzte Page kopiert werden ansonsten sehe ich da keine Probleme (außer natürlich das mit größeren Daten auch die Mapping-Kosten steigen, wogegen es meinen Segmenten ziemlich egal ist ob diese 3 Bytes oder 3 GBytes repräsentieren).

Also fread würde einfach zum Service sagen, gib mir mal den Speicher von da bis da (den Bereich wo die zu lesenden Daten drin sind) und der Service gibt dann als Antwort ne ID für SharedMem zurück die in den Clienten eingeblendet wird und fread kann aus diesem "Cache" dann in den Buffer des Clienten kopieren.
Wenn der Service immer seinen Speicher an den Client weitergibt damit sich dieser daran bedienen kann dann gibt es bei Dir prinzipiell kein Zero-Copy. Überlege Dir mal wie damit ein HDD-Treiber arbeiten müsste, der müsste die gewünschten Sektoren erst mal in eigenen Speicher holen um dann diesen Speicher seinem Client zu zeigen damit dieser sich die Daten dort raus kopiert. Daran gefallen mir persönlich 2 Dinge nicht: zum einen der Zwang zum teuren und unsinnigen Kopieren und zum anderen das für das Memory-Sharing usw. ne ganze Menge Syscalls erforderlich sein dürften. Ein ls über ein Verzeichnis mit 10000 Dateien möchte ich damit nicht machen müssen.

Einziges Problem mit dem Caching ist, was passiert wenn dem Storage-Server der virtuelle Speicher ausgeht und noch eine Datei geöffnet werden soll?
Wenn der Cache eng wird müssen eben die am längsten nicht mehr benutzen Daten raus fliegen. Das ist die Basis-Philosophie eines jeden Caches.

Leider habe ich nicht vor so schnell mein OS auf eine 64bit Architektur zu portieren bzw. neuzuschreiben.
Das ist ungeschickt, der kommende Mainstream ist 64 Bit.
Eben weil es mit Segmentierung keine Plattform gibt die 64Bit-tauglich ist (böses AMD!!) habe ich mich entschlossen was eigenes zu bauen.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #72 am: 31. August 2010, 21:04 »
Zitat von: erik
Ich wollte den Heap über mehrere Segmente verteilen, eventuell sogar für jede angefragte Objekt-Größe ein eigenes Segment oder zumindest etwas in dieser Richtung. Genau weiß ich das noch nicht. Es wird auf jeden Fall nicht für jeden Aufruf von malloc ein neues Segment erstellt, da wären die Segmente ziemlich schnell alle und der Verschnitt wäre riesig (weil ein Segment immer ganze Pages belegt). Vielmehr möchte ich das gleichgroße Objekte alle im selben Segment drin sind und wie ein Array verwaltet werden. Der Vorteil meiner Segmente ist das ich die einzelnen Segmente unabhängig voneinander Vergrößern und auch wieder Verkleinern kann, ich hab nicht nur einen virtuellen Adressraum, wo man schon mal mit Konflikten rechnen muss, sondern ziemlich viele die eben völlig unabhängig voneinander sind.
Klingt wieder verdächtig nach dem SlabAllocator ;) So schlecht scheint das Konzept also nicht zu sein.

Zitat von: erik
Wenn der Service immer seinen Speicher an den Client weitergibt damit sich dieser daran bedienen kann dann gibt es bei Dir prinzipiell kein Zero-Copy. Überlege Dir mal wie damit ein HDD-Treiber arbeiten müsste, der müsste die gewünschten Sektoren erst mal in eigenen Speicher holen um dann diesen Speicher seinem Client zu zeigen damit dieser sich die Daten dort raus kopiert. Daran gefallen mir persönlich 2 Dinge nicht: zum einen der Zwang zum teuren und unsinnigen Kopieren und zum anderen das für das Memory-Sharing usw. ne ganze Menge Syscalls erforderlich sein dürften. Ein ls über ein Verzeichnis mit 10000 Dateien möchte ich damit nicht machen müssen.
Also den HDD-Treiber interessiert es prinzipiell schon mal gar nicht was mit den Daten passiert, der läd sie nur und gibt sie einfach an den VFS-Service weiter (da findet kein kopieren statt) und damit ist der Speicher für ihn auch weg.
Ich weiß nun nicht wie "ls" genau funktioniert, aber ich stelle mir das schon so vor, das er für jede einzelne Datei in dem Verzeichnis mind. 1 Syscall machen muss (müsste die Datei nicht sogar vorher geöffnet werden nur um an die Infos zu kommen, dann wären da ja sogar noch mehr Syscalls nötig).
Die Daten über die Dateien liegen im VFS-Service und dieser macht in dem Fall kein Memory-Sharing mit dem Clienten!
Der Client würde seine Anfrage per Pipe stellen und wenn er das geschickt macht, kann er sogar mehrere Anfragen mit einmal in die Pipe schreiben (so könnte ich sogar einige Syscalls vermeiden, wo auch mal ein Vorteil meiner UserSpace Pipe´s zum Tragen kommt).

Zitat von: erik
Das ist ungeschickt, der kommende Mainstream ist 64 Bit.
Ja, aber nicht überall ist die Situation mit den PCs so wie hier bei uns in Deutschland, ich möchte sogar behaupten die ist nirgends so wie hier. Damit meine ich das die Mehrheit der Leute relativ neue PCs haben.
Meistens ist es eher so das noch viele auf dem Stand von z.B. Athlon XP und sowas sind.
Was du eher meinst sind Spiele-PCs, aber das sollte weltweit gesehen, wohl eher die Minderheit sein.
Dann kommt noch hinzu das ich gerne auf realer Hardware teste und das auf so viel wie möglich und da sind viele 64bit Systeme nicht gerade günstig. Wenn ich mir da überlege wie viele 32bit Systeme ich mehr als günsitg erstanden habe.
Auch ist z.B. ARM (meines Wissens nach) noch nicht bei 64bit angekommen (um mal ne andere Platform zu nennen).
Also ich will erstmal ein halbwegs brauchbares System in 32bit haben. Dann habe ich vor ein neues für 64bit zu schreiben.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #73 am: 01. September 2010, 08:32 »
Hallo,


Klingt wieder verdächtig nach dem SlabAllocator ;) So schlecht scheint das Konzept also nicht zu sein.
Naja, ich bin mir noch nicht sicher ob man damit wirklich einen generischen Heap bauen kann. Für viele (kleine) gleichartige Objekte ist diese Variante schon recht toll aber was ist wenn das Programm viele unterschiedlich große Objekte erzeugen will? Mehr als 1000 Heap-Segmente will ich definitiv auch nicht haben weil ja immer mit etwas Verschnitt gerechnet werden muss und auch mit jedem Segment der Verwaltungsaufwand steigt. Ich hab die letzten Monate eine Reihe interessanter Heap-Management-Artikel gelesen die teilweise recht unterschiedliche Ansätze favorisieren, da muss ich auf jeden Fall noch mal gründlich drüber nachdenken welche dieser Lösungen überhaupt zu meinen Segmenten passt. Eventuell programmiere ich auch verschiedene Lösungen (obwohl ich so viel Aufwand gerne vermeiden möchte) und schau mir dann an welche Lösung sich in der Praxis am besten bewährt. Bevor ich einen C-Compiler hab muss ich aber erst mal eine Primitiv-Version in Assembler bauen und die wird wohl einfach in einem einzelnen Segment eine verkettete Liste (ähnlich dem was DOS früher gemacht hat) nehmen.

Also den HDD-Treiber interessiert es prinzipiell schon mal gar nicht was mit den Daten passiert, der läd sie nur und gibt sie einfach an den VFS-Service weiter (da findet kein kopieren statt) und damit ist der Speicher für ihn auch weg.
Du meinst der HDD-Treiber alloziert Speicher (um dort Daten rein zu legen), gibt diesen Speicher weiter (an seinen Client, einen Dateisystem-Treiber) und damit ist der Speicher vom HDD-Treiber wieder entzogen (so als hätte er free benutzt)? Das ist ein sehr merkwürdiges Konzept, das mag zwischen VFS, Dateisystem-Treibern und Block-Device-Treiber noch funktionieren aber wie ist das z.B. mit USB oder Sound oder seriellen Schnittstellen? Außerdem wie geht das beim Schreiben auf eine HDD? Muss da der HDD-Treiber erst Speicher allozieren damit das VFS da was rein legen (kopieren) kann und der HDD-Treiber (nachdem die Daten auf die HDD geschrieben wurden) diesen Speicher wieder freigeben muss? Speicher von unten nach oben zu reichen halte ich für extrem ungeschickt! Das macht IMHO nur in ganz speziellen Situationen sind und wiederspricht auch allen vorhandenen Programmier-Paradigmen (einem printf wird ja auch der Speicher mit dem String übergeben). Anders zu sein ist IMHO an sich schon mal was gutes aber das lässt sich nicht auf alles anwenden. Ich weiß ich reite ziemlich auf dem Zero-Copy-Prinzip rum aber das verspricht eben die maximale Performance (unnützes kopieren kostet nur Zeit und Energie) und sollte von daher angestrebt werden. Wenn man im VFS einen Cache haben will, der ja immer ein Kopieren erfordert, dann macht man das ja weil man sich insgesamt davon einen Performance-Vorteil erhofft (ein paar mal Kopieren ist dann doch schneller als ein paar mal auf die HDD zu warten).

Der Client würde seine Anfrage per Pipe stellen und wenn er das geschickt macht, kann er sogar mehrere Anfragen mit einmal in die Pipe schreiben (so könnte ich sogar einige Syscalls vermeiden, wo auch mal ein Vorteil meiner UserSpace Pipe´s zum Tragen kommt).
An dieser Stelle könnte ich auch mehrere Anfragen (weil das ja alles die gleichen sind) in einen RPC-Request packen und sagen dass das ein Vorteil meiner flexiblen Message-Größe ist. ;) Klar kann man für bestimmte Situationen eine extra Optimierung vornehmen aber wie viele Alltagsaufgaben profitieren den wirklich davon?

Auch ist z.B. ARM (meines Wissens nach) noch nicht bei 64bit angekommen (um mal ne andere Platform zu nennen).
Ja, bei ARM hat man den Anbruch der 64 Bit-Epoche dem Anschein nach noch völlig verschlafen und das wo doch auch bereits Handys mal 1 GByte RAM haben können.

Also ich will erstmal ein halbwegs brauchbares System in 32bit haben. Dann habe ich vor ein neues für 64bit zu schreiben.
Versuch doch Dein OS so zu programmieren das es sich für beide Welten eignet. Ich werde meinen OS-Kernel wohl zu großen Teilen in Assembler coden müssen und trotzdem wird er sich für beide Welten assemblieren lassen, ich denke es wird nur wenige Stellen geben wo wirklich unterschiedlicher Programm-Code erforderlich ist (z.B. bei den Segment-Descriptoren).


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #74 am: 01. September 2010, 10:42 »
Ich denke mal beim Heap sprichst du vom User-Heap? Da ist natürlich ein anderer Ansatz wesentlich besser geeignet. Obwohl die (z.B. Linux, Solaris) auch den SlabAllocator dafür nutzen und es scheint zu funktionieren.

Was den Heap allgemein betrifft, ist das so eine der Sachen die ich nie richtig verstanden habe und ich habe auch das Gefühl das viele sich da an Linux/Unix orientieren, aber ich bin der Meinung das deren Heap-Prinzip nicht so toll für Multithreading geeignet ist.

Zitat von: erik
Du meinst der HDD-Treiber alloziert Speicher (um dort Daten rein zu legen), gibt diesen Speicher weiter (an seinen Client, einen Dateisystem-Treiber) und damit ist der Speicher vom HDD-Treiber wieder entzogen (so als hätte er free benutzt)? Das ist ein sehr merkwürdiges Konzept, das mag zwischen VFS, Dateisystem-Treibern und Block-Device-Treiber noch funktionieren
Das ist doch erstmal das einzige was mich interessiert ;)

Zitat von: erik
Außerdem wie geht das beim Schreiben auf eine HDD? Muss da der HDD-Treiber erst Speicher allozieren damit das VFS da was rein legen (kopieren) kann und der HDD-Treiber (nachdem die Daten auf die HDD geschrieben wurden) diesen Speicher wieder freigeben muss?
Nein, der User hat ja seinen Buffer aus dem die Daten kommen, die (Daten) werden dann in neuen Speicher kopiert welcher an den VFS-Service weitergegeben wird (bzw. wenn nicht die ganze Datei geändert wird, werden die neuen Daten einfach über die alten Daten geschrieben) und dieser gibt den Speicher dann wiederrum an den HDD-Treiber weiter.
Der Treiber schreibt das ganze dann auf die HDD und gibt den Speicher wieder frei (das muss er auch beim Lesen machen, das habe ich glaub ich nicht so deutlich gesagt).

Das größte Problem was ich bisher nicht gelöst habe (aber ich habe schon eine Idee dafür) ist, dass ich nicht weiß wie ich es einem Treiber ermögliche das er rausbekommt, welche physikalische Adresse hinter einer virtuellen Steckt. Ich dachte mir das ich dafür nen Syscall mache und bei jedem Aufruf wird überprüft ob es ein Treiber ist (das ist bei mir immer dann der Fall wenn der Prozess auf Ports zugreifen darf).
Genauso müsste ein Prozess dann auch Speicher als nicht auslagerbar markieren dürfen (was dann halt schon bei der Allokierung passieren muss).
Obwohl ich mit dem Auslagern wohl die größten Probleme bekommen werde, da ich dafür noch gar keine Idee habe, wie das zu lösen ist, deswegen ignorier ich das im Moment auch fleissig ;)

Zitat von: erik
Ja, bei ARM hat man den Anbruch der 64 Bit-Epoche dem Anschein nach noch völlig verschlafen und das wo doch auch bereits Handys mal 1 GByte RAM haben können.
Dem würde ich jetzt entgegenhalten naund ;) Ich meine nur weil die schon bei 1GB RAM angekommen sind, heißt das ja noch lange nicht das denen der virtuelle Speicher ausgeht.
Ich denke mal Handys brauchen nicht unbedingt ne 64bit Architektur, aber schaden kann es natürlich nicht (mal von den Transistoren abgesehen, die du dann mehr bräuchtest).

Zitat von: erik
Versuch doch Dein OS so zu programmieren das es sich für beide Welten eignet.
Gerade das werde ich nicht tun! Ich bin der Meinung wer einen Mikrokernel (und nicht einen Mix aus Mikro und Monolith) schreibt, der sollte für jede Architektur einen extra Mikrokernel schreiben. Ist der Kernel wirklich klein, würde ich sogar sagen, das es sich lohnen würde diesen in Assembler zu schreiben.

Der Punkt ist, ich optimiere viele Sachen für die x86 Architektur und möchte nicht noch mehr Abstraktionsebenen einbauen, nur damit der Kernel leichter auf eine neue Architektur portiert werden kann. Gerade bei nem Mikrokernel ist doch der Aufwand den Kernel für ne andere Architektur (wo dann auch deren Besonderheiten beachtet werden, bzw. ausgenutzt werden) neu zu schreiben nicht sonderlich groß!
Wenn du die Interfaces gleicht behälst solltest du die meisten Sachen einfach nur neu kompilieren brauchen. Ich plane im Moment sogar wie ich meinen Device-Server portabel gestalte, da ja auf der ARM Architektur sowas wie ein BIOS nicht existiert. Da würde ich dem Device-Server wahrscheinlich als Startmodul auf jeder Architektur nen angepasstest Skript mitgeben, welches dann bestimme Module in einer bestimmten Reihenfolge lädt.
Damit wäre es dann einfach zu sagen, das dieses und jenes Gerät diesen und jenen Speicher/IO-Ports benutzt ohne das ich dafür Code ändern müsste (ziel wäre es nur die Adresse und IO-Ports in einem Skript zu ändern und schon hat man die Unterstützung für ein anderes Board ohne das man irgendwelchen Code neukompiliert hat).

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #75 am: 01. September 2010, 18:07 »
Hallo,


Ich denke mal beim Heap sprichst du vom User-Heap?
Ja, ich habe die ganze Zeit vom Heap der User-Mode-Applikationen gesprochen. Den Speicher den der Kernel verwaltet ist bei mir der lineare Speicher.

Was den Heap allgemein betrifft, ist das so eine der Sachen die ich nie richtig verstanden habe und ich habe auch das Gefühl das viele sich da an Linux/Unix orientieren, aber ich bin der Meinung das deren Heap-Prinzip nicht so toll für Multithreading geeignet ist.
Ich weiß nicht ob die Default-Mechanismen von Linux usw. so schlecht sind aber aus irgend einem Grund muss es ja die teuren kommerziellen Heap-Librarys geben.

Das ist doch erstmal das einzige was mich interessiert
Das ist dann aber ziemlich kurzsichtig. Soll Dein OS nicht mal per LAN kommunizieren oder eine simple serielle Schnittstelle nutzen können?

Zitat von: erik
Außerdem wie geht das beim Schreiben auf eine HDD? Muss da der HDD-Treiber erst Speicher allozieren damit das VFS da was rein legen (kopieren) kann und der HDD-Treiber (nachdem die Daten auf die HDD geschrieben wurden) diesen Speicher wieder freigeben muss?
Nein, der User hat ja seinen Buffer aus dem die Daten kommen, die (Daten) werden dann in neuen Speicher kopiert welcher an den VFS-Service weitergegeben wird
Hier wird dann doch der Speicher vom Client an den Service weitergegeben? Hm, das wird immer komplexer. Also den Mechanismus für beide Richtungen anzubieten scheint zwar verlockend aber ist bestimmt auch komplexer als sich auf eine Richtung zu beschränken. Oder haben Deine Memory-Sharing-Mechanismen nichts direkt mit dem IPC-Mechanismen zu tun? Wenn nicht, dann kosten sie natürlich wieder extra Syscalls.

Der Treiber schreibt das ganze dann auf die HDD und gibt den Speicher wieder frei (das muss er auch beim Lesen machen, das habe ich glaub ich nicht so deutlich gesagt).
Verstehe ich das richtig das der HDD-Treiber den Speicher der Applikation oder des VFS frei gibt? Oh man, das klingt ganz schön schräg.

dass ich nicht weiß wie ich es einem Treiber ermögliche das er rausbekommt, welche physikalische Adresse hinter einer virtuellen Steckt.
Das ist einfach, der Kernel-Code schaut halt einfach selber ins Paging-Directory und schon hat er die physische Adresse. Das ist ein recht kurzer Syscall.

(das ist bei mir immer dann der Fall wenn der Prozess auf Ports zugreifen darf).
Falls Du dieses mal mit "Ports" die I/O-Ports meinst dann muss ich Dich enttäuschen es gibt auch HW die nur mit Memory-Mapped-I/O arbeitet und keine Ports hat.

Zitat von: erik
Ja, bei ARM hat man den Anbruch der 64 Bit-Epoche dem Anschein nach noch völlig verschlafen und das wo doch auch bereits Handys mal 1 GByte RAM haben können.
Dem würde ich jetzt entgegenhalten naund ;) Ich meine nur weil die schon bei 1GB RAM angekommen sind, heißt das ja noch lange nicht das denen der virtuelle Speicher ausgeht.
Aber der physische Adressraum könnte bald zu knapp werden. Sowas wie einem iPad würden sicherlich 2 GBytes RAM gut tun aber dann sind die 32Bit auch (fast) am Ende, schließlich muss noch allerlei Memory-Mapped-Hardware mit in den physischen Adressraum mit rein (ARM kennt keine I/O-Ports, das ist eine x86-Besonderheit).

Ich denke mal Handys brauchen nicht unbedingt ne 64bit Architektur, aber schaden kann es natürlich nicht (mal von den Transistoren abgesehen, die du dann mehr bräuchtest).
Das mit den Transistoren dürfte sich auf sehr wenige Prozent beschränken, das meiste Silizium wird in heutigen Handys für die ganze Peripherie (Bluetooth, USB, Display-Controller .....) benötigt.

Zitat von: erik
Versuch doch Dein OS so zu programmieren das es sich für beide Welten eignet.
Gerade das werde ich nicht tun! Ich bin der Meinung wer einen Mikrokernel (und nicht einen Mix aus Mikro und Monolith) schreibt, der sollte für jede Architektur einen extra Mikrokernel schreiben. Ist der Kernel wirklich klein, würde ich sogar sagen, das es sich lohnen würde diesen in Assembler zu schreiben.
Okay, dafür sind sich die 32 Bit-Version und die 64 Bit-Version meiner CPU zu extrem ähnlich als das es sich da lohnen würde unterschiedlichen Code zu verfassen, bei x86 könnte es sich vielleicht schon an einigen Stellen lohnen. Obwohl es ne Menge OSe gibt die auf den unterschiedlichsten CPU-Architekturen laufen und nur sehr kleine Teile davon spezifisch sind, die überlassen dem Compiler die Anpassungsarbeit.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #76 am: 01. September 2010, 18:29 »
Zitat von: erik
Ich weiß nicht ob die Default-Mechanismen von Linux usw. so schlecht sind aber aus irgend einem Grund muss es ja die teuren kommerziellen Heap-Librarys geben.
Mir gefällt nicht das der Heap, mehr oder weniger zusammenhängend ist und von oben (wie ein Stack) herunter wächst.

Zitat von: erik
Das ist dann aber ziemlich kurzsichtig. Soll Dein OS nicht mal per LAN kommunizieren oder eine simple serielle Schnittstelle nutzen können?
Da hast du mich in dem Moment falsch verstanden. Ich will nicht die eine Methode für alles finden (sowas wie ne Weltformel), sondern nutze das was ich (also mein Kernel) zur Verfügung habe aus, sprich für verschiedene Probleme, verschiedene Lösungen.

Zitat von: erik
Hier wird dann doch der Speicher vom Client an den Service weitergegeben? Hm, das wird immer komplexer. Also den Mechanismus für beide Richtungen anzubieten scheint zwar verlockend aber ist bestimmt auch komplexer als sich auf eine Richtung zu beschränken. Oder haben Deine Memory-Sharing-Mechanismen nichts direkt mit dem IPC-Mechanismen zu tun? Wenn nicht, dann kosten sie natürlich wieder extra Syscalls.
Also erstmal was hast du immer mit deinen Syscalls ;) Ich weiß nicht wie du dir das vorstellst, aber wenn ich von SharedMem rede, dann läuft das bei mir folgender Maßen ab.
Du machst nen Syscall wo du ne BaseAddr und eine Länge (in Pages) angibst (sowie nen Flag ob der Speicher dann read-only ist oder nicht), der Kernel speichert dann die physischen Adressen der einzelnen Pages in einer Liste und markiert diese als SharedMem (damit sie nicht ausgelagert werden können) und du (der Syscall-Aufrufer) bekommst ne ID zurück. Als nächstes musst du noch einen Syscall machen (ich weiß nicht toll, aber mir ist nichts besseres eingefallen) in dem du sagst das du nem anderen Prozess Zugriff geben willst. Dann kannst du die ID an nen anderen Prozess weitergeben (den Prozess den du gerade Zugriff gegeben hast) und dieser macht dann mit der ID nen Syscall das er den Speicher mappen will, ist genug virtueller Speicher vorhanden wird das gemacht. Bist du (der Client, also der der den Speicher gemappt hat) fertig mit deiner Arbeit, rufst du nen Syscall auf, dass du den Speicher wieder unmappen willst und das wird dann auch gemacht, der Speicher wird aber in dem Sinne nicht freigegeben, sondern ist ja noch beim eigentlichen "Owner" vorhanden.

Das sollte auch ungefähr die Prozedur sein, wie sie auf allen (fast??) OS zur Verfügung gestellt wird.

Zitat von: erik
Verstehe ich das richtig das der HDD-Treiber den Speicher der Applikation oder des VFS frei gibt? Oh man, das klingt ganz schön schräg.
Siehe oben, wird nicht freigegeben, sondern ge-unmappet (scheiß denglisch ;) ).

Zitat von: erik
Falls Du dieses mal mit "Ports" die I/O-Ports meinst dann muss ich Dich enttäuschen es gibt auch HW die nur mit Memory-Mapped-I/O arbeitet und keine Ports hat.
Schitt erwischt :( Da muss ich mir auch nochmal Gedanken machen, wie ich einem Prozess (Treiber) erlauben darf nen bestimmten physikalischen Speicherbereich in seinen Adressraum zu mappen.

Zitat von: erik
Das ist einfach, der Kernel-Code schaut halt einfach selber ins Paging-Directory und schon hat er die physische Adresse. Das ist ein recht kurzer Syscall.
Das ist klar, aber das will ich nicht jedem X-beliebigen Prozess erlauben, sondern nur Treibern!

Zitat von: erik
Obwohl es ne Menge OSe gibt die auf den unterschiedlichsten CPU-Architekturen laufen und nur sehr kleine Teile davon spezifisch sind, die überlassen dem Compiler die Anpassungsarbeit.
Ja, aber zu welchem Preis? Ich meine das Linux auf allen Architekturen die selben Page-Tables nutzt, aber je nach dem wie das Paging dann auf der Architektur Hardware mäßig implementiert ist, sehen die dann in der Hardware ganz anders aus.
Außerdem gefällt mir diese ganze bedingte Kompilieren nicht, der Source sieht nicht mehr wirklich "schön" aus und ich habe auch oft Probleme den richtigen Code zu finden und zu lesen.
Außerdem wäre mir das viel zu viel Arbeit, denn du musst ja höllisch aufpassen, was du dann alles auf ner neuen Architektur implementieren musst, welche Funktionen eigentlich gar nichts machen usw.

 

Einloggen