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 ... 31 32 [33] 34 35 ... 43
641
Lowlevel-Coding / Re:Shared Memory
« am: 25. September 2010, 12:32 »
Zitat von: taljeth
Ich weiß ja nicht, wo du deine x86-Fälschung erworben hast, die das so macht, aber mein x86 sichert von sich aus bei einem Interrupt oder Trap Gate nur ss, esp, eflags, cs und eip auf den Stack. Der Rest landet nur dann auf dem Stack, wenn du das so programmierst. Bei einem Task Gate geht sogar alles direkt in eine andere Struktur (nämlich das TSS).
Naja, ich bin halt einfach davon ausgegangen das man alles auf dem Stack speichert, weil es das schnelleste und einfachste ist. Es dann nochmal umzukopieren wäre ja quatsch.

Zitat von: erik
Das bedeutet das wenn Du asynchrones I/O implementieren möchtest soll das über noch mehr Ports (und damit Threads) im Service gehen? Ich gebe zu das ich über asynchrones I/O auch noch nicht so viel nachgedacht habe aber diese Idee erscheint mir nicht sonderlich geschickt.
Ich wollte damit nur sagen, dass mein Konzept bei A-I/O nicht mehr funktioniert, aber diese Baustelle werde ich frühestens bearbeiten wenn alles andere läuft und bis dahin vergeht noch ne ganze Weile.

Zitat von: erik
Doch, sehr lange und intensiv sogar, aber ich hatte kurz vergessen das die x86-CPU die Register ja zwangsweise in den Speicher schreibt aber auch so bin ich davon ausgegangen das man das gesicherte Register-Set vom Stack in die Thread-Descriptor-Struktur kopiert und wenn man einen anderen Thread weiterlaufen lassen will dann wird sein Register-Set eben in den CPU-Lokalen-Kernel-Stack kopiert und ein IRET gemacht.
Naja, du vergisst, dass auf dem Stack aber nicht nur die Register liegen, da liegen auch noch Funktionsargumente, lokale Variablen usw., das müsstest du dann alles mit in den Thread-Descriptor speichern und das artet dann mal schnell darin aus, das du den gesamten Stack woanders hinkopierst, nur um zu erreichen das du nur einen Stack im Kernel verwendest. Das einzigste was du dadurch erreichen würdest wäre, dass du pro CPU einen Stack mehr hast als normalerweise nötig.

Ich bin jetzt mal ganz einfach davon ausgegangen, dass jeder Thread auch mal den Syscall macht und das der Kernel unterbrechbar ist.

Übrigens wiedersprichst du da deiner eigenen Philosophie des zero-copy (ich betrachte das Speichern auf dem Stack nicht als kopieren in dem Sinne, weil mind. 1 Register sowieso erstmal irgendwo zwischen gespeichert werden muss um den Rest dann irgendwo zu speichern).

Zitat von: erik
Selbst bei x86-64 ist ein Register-Set nur 128 Bytes groß und dafür einen kompletten Stack zu reservieren finde ich eher ungeschickt, bei den paar Bytes fällt das kopieren nun wahrlich nicht ins Gewicht (das passt ja bequem in den L1-Cache so das der von Dir erhoffte Performance-Vorteil vermutlich weniger als 10 Takte pro Context-Switch beträgt). Im Tutorial wird doch wimre auch nur ein TSS pro CPU empfohlen, wo mir dann auffällt das Du dann dort immer einen anderen Kernel-Stack eintragen musst (also Speicherzugriffe) oder Du hast so viele TSS wie es Threads gibt und da dürften Dir dann doch ziemlich schnell die GDT-Einträge ausgehen (vor allem weil Du ja mit Threads seeeehr großzügig bist).
Du hast, wie gesagt, das Szenario Syscall vergessen und das die Kernel-Funktionen ja auch den Stack verwenden. Wie kommst du auf 10 Takte bei 128byte? Zumal es mehr als nur die 16 Register sind, da wäre noch das RIP und das RFlags Register.
Und ja ich verwende nur ein TSS pro CPU, weil es halt nötig ist. Denn keiner von uns wird wohl Hardware-Taskswitching auf der x86-Architektur nutzen (wenn doch komm ich dem gleich mit der Portabilität ;) )!?

Zitat von: erik
Ich möchte das ein Service bei der Erstellung seines Message-Targets bestimmen kann wie viele Threads maximal für dieses Message-Target erstellt werden dürfen, das bedeutet dann das wenn mehr Anfragen gleichzeitig kommen das dann gequeued werden muss. Dieses Maximum darf auch 1 betragen. Aber das ein bereits vorhandener Thread in dem Prozess benutzt werden soll ist definitiv nicht vorgesehen. Es wird weder aktives abholen von Messages geben (eben wegen den Problemen mit der unbekannten Message-Größe) und auch keine Unterbrechung eines Threads (in der Art der Unix-Signale, das hat mir zu viele Nachteile für die Signal-Handler bei der Benutzung von Ressourcen wie malloc usw.).
Ok, wenn du das so machen willst, darfst du mir nie mehr damit kommen, das man nicht alzu sehr von gewohnten Weg abweichen sollte ;)

Ich sag mal ne normal GUI-App zu schreiben/portieren dürfte noch gehen, aber wenn es dann zu sachen kommen die normaler Weise nicht blockieren wenn keine Nachricht da ist, sondern weiter arbeiten, da stelle ich es mir dann schon schwierig vor (Bsp. Spiele, die warten ja auch nicht bis die Taste gedrückt wurde, sondern es wird geguckt, wurde eine gedrückt und dann wird der nächste Frame berechnet).

Aber ansich ist die Idee von daher gut, weil man damit zum Multithreading gezwungen wird, macht die Sache nicht einfacher, aber dann gibt es vielleicht irgendwann mal mehr Programme mit denen man Vorteile aus mehreren Kernen holen kann.

Zitat von: erik
Klar kann es sein das der Pool mal ziemlich voll wird aber dann muss der eben etwas geleert werden. Es kommt letztendlich auf eine gute Pool-Verwaltungsstrategie an aber wenn ich die finden sollte werde ich wohl weniger Speicher verbrauchen als Dein Konzept.
Das klingt für mich wie nach dem Kontept eines Garbage-Collectors. Wird von allen als das Allheilmittel angepriesen (weil sich der dumme Programmierer nicht mehr um die Speicherverwaltung kümmern muss). Jedes Mal wenn ich das Wort Garbage-Collector höre, dreht sich bei mir im Magen alles um.
Meine Erfahrung von Programmen die in Java oder python oder anderen Sprachen mit einem Garbage-Collector geschrieben sind, der wird immer in einem bestimmten Zeit-Interall aufgerufen, wo er halt aufräumt und in der Zeit geht die Performance meistens in den Keller.
Sowas hört sich in der Theorie immer toll an, aber in der Praxis hapert es fast immer :(

Zitat von: erik
Bitte nicht übel nehmen aber das ist völliger Quatsch! Eine TCP-Verbindung wird über die 2 IP-Addressen und die 2 Port-Nummern (jeweils vom Client und vom Server) unterschieden und selbst wenn davon immer eine IP-Adresse und ein Port gleich sind (also die vom Server) so sind doch trotzdem mit IPv4 theoretisch bis zu 2^48 Verbindungen zu einem einzelnen Web-Server möglich (mit IPv6 entsprechend mehr).
Das klingt doch schon ganz anders und ist auch viel logischer!
642
Lowlevel-Coding / Re:Shared Memory
« am: 25. September 2010, 07:45 »
Zitat von: svenska
Wenn du einen Webserver auf Port 80 hast und der kriegt ne Anfrage, dann wird ein lokaler Port zugeteilt (z.B. 38855) und über den läuft die Kommunikation. Dein Webserver kann also keine 64k TCP-Verbindungen gleichzeitig halten, weil es soviele Ports dann nicht gibt. Korrigiert mich, wenn ich hier falsch liege.
Genauso habe ich das auch in Erinnerung, aber wie macht das dann ein Web-Server? Denn seien wir mal ehrlich, 64k gleichzeitige Zugriffe sind nicht wirklich viel für bestimmte Web-Seiten.

Zitat von: taljeth
Zero-copy ist ein Taskwechsel eh nicht, ob du die Register jetzt auf den Stack oder woanders hin sicherst.
Also ich weis ja nicht wie bei euch ein IRQ abläuft, aber sobald ein IRQ aufgerufen wurde (und das gilt auch für den Scheduler) sind alle Register schon auf dem Stack, also würde es durchaus etwas kosten diese nochmal, vom Stack, irgendwo hinzusichern! Ein Thread-Wechsel sollte nicht mehr als ein Austausch von "ESP" sein und bei einem Prozess-Wechsel wird dann nur noch zusätzlich "CR3" verändert.
643
Lowlevel-Coding / Re:Shared Memory
« am: 24. September 2010, 23:53 »
Zitat von: taljeth
Du könntest theoretisch auch nur einen Kernelstack pro CPU benutzen und den Zustand woanders hin wegkopieren.
Dazu sag ich erstmal zero-copy ;) und was unterscheidet den Speicher (den du so oder so benötigst und nur der Kernel draufzugreifen darf) wo du die Daten hinkopierst von einem Stack?
644
Lowlevel-Coding / Re:Shared Memory
« am: 24. September 2010, 23:18 »
Zitat von: erik
Also Du möchtest für jeden Client in Deinem Service einen extra Port aufmachen und auch einen extra Thread starten, verstehe ich das richtig? Bei welcher Aktion des Clients wird ein neuer Port im Service geöffnet? Z.B. bei jedem open? Ich bin mir nicht ganz sicher aber ich kann mir gut Vorstellen das Deine Services vor lauter Threads und Ports geradezu überquellen. Wie viel Speicher kostet eigentlich so ein Port (Verwaltungsstrukturen usw.) und wie aufwendig sind die Syscalls zum erstellen bzw. löschen eines Ports? Meine Services sollen genau einen Port (bei mir nenne ich das Message-Target) haben oder auch 2 wenn synchrones RPC und asynchrones IPC angeboten werden soll. Das wird IMHO völlig reichen.
Ein Port für jedes Open wäre ja quatsch, weil solange wie ich kein A-I/O habe kann ein Thread sowieso nur eine Datei gleichzeitig lesen/schreiben.
Der Port wird nur erstellt wenn er auch wirklich benötigt wird, sprich wenn eine Anwendung keine Dateien öffnet dann wird auch kein Port erstellt oder wenn sie nur aus einem Thread besteht (was ja leider noch auf die meisten Anwendungen zutrifft) dann wird nur ein Port geöffnet.
Ich würde dir gerne sagen wieviel Speicher so eine Portstruktur bei mir braucht, da mir aber vorhin mein Laptop-Netzteil abgeraucht ist und ich jetzt an dem Laptop meiner Freundin sitze kann ich dir das leider nicht genau sagen, aber es ist auf jeden Fall weniger als bei nem Thread ;)

Zitat von: erik
Das würde bedeuten wenn ein Web-Server mit vielen Threads arbeitet um möglichst viele Verbindungen parallel zu betreiben würden in Deinem TCP-Service auch ne Menge an Ports und Threads existieren, selbst wenn die Daten nur so dahin tröpfeln, verstehe ich das richtig?
Ich weiß gar nicht wie sowas unter anderen OSs gemacht wird, aber der Web-Server ansich macht ja für jeden Clienten einen neuen Thread auf (wo sich mir gerade die Frage stellt wie das überhaupt funktioniert, ich erinnere mich da an einen Port (TCP-Port) pro Client, aber das kann nicht stimmen) und je nachdem über wieviele TCP-Ports das dann läuft, so viele Threads wären dann auch im Service.

Zitat von: erik
Erstmal besteht ein Thread aus mehr als nur seinem Stack, da gibt es noch Verwaltungsstrukturen im Kernel und Listen für den Scheduler und sicher noch einiges anderes. Zum anderen, wozu brauchst Du pro (User-Mode-)Thread einen eigenen Kernel-Stack? In meinem System wollte ich einen Kernel-Stack pro CPU, wird das bei x86 irgendwie anders gemanaged?
Mit der x86-Architektur hast du dich noch nicht so viel beschäftigt oder?

Jedes Mal wenn du einen Aufruf in den Kernel machst, brauchst du nen Kernel-Stack. Wie willst du es nun bewerkstelligen wenn ein IRQ deinen Scheduler aufruft (was auch alles noch über diesen Stack läuft) und ein anderer Thread zum Zug kommt? Du musst die Daten die auf dem Stack liegen ja behalten und da reicht dann auch nicht ein Stack pro CPU.

Zitat von: erik
Auf was für eine gleiche Datenstruktur sollten die Threads in einem Service gleichzeitig (und vor allem für die ganze Verarbeitungszeit) zugreifen?
Erwischt ;)

Da habe ich doch tatsächlich (in meinen Gedanken) die ganzen Verwaltungsdaten (was halt in seiner FILE struktur drinsteckt) mit in den Service gepackt. Aber spätestens beim HDD-Treiber machen die Popup-Threads dann wirklich keinen Sinn mehr. Denn was bringen dir viele Threads die von ein und der selben HDD lesen wollen (und wir lassen SATA job-queueing mal außen vor)? Die müssten dann ja blockieren, da die HDD gerade von einem anderen Thread benutzt wird. Wo sich mir dann auch die Frage stellt, willst du eigentlich einem Programm auch die Möglichkeit geben, das keine Popup-Threads erstellt werden, sondern das alles nur über einen Thread läuft (der nicht erstellt werden muss)?

Zitat von: erik
Ja, ich möchte da einen Pool haben wo die Stacks und Verwaltungsstrukturen erstmal auf Vorrat liegen. Der Unterschied ist das ich diesen Vorrat für jeden Service benutzen kann der gerade Aufträge bekommt und das nicht starr festgelegt ist. Auch in meinem Konzept wird es eine Menge Threads geben aber die Threads sind dort wo auch Arbeit verrichtet wird und gammeln nicht in irgendwelchen blockierenden Syscalls rum.
Ok, aber nach welchen Kriterium entscheidest du wieviele Threads in diesen Pool kommen?

Bei dir sehe ich dann, wie gesagt, das Problem das du entweder viel Zeit mit der Thread Erstellung verbringst (was passiert eigentlich wenn die Nachricht abgearbeitet ist bzw. muss der User den Thread selbst beenden und wo kommt er dann hin?) oder du halt viel zu viele Threads hast, die nichts machen und sinnlos im Pool rumliegen ;) Damit hättest du dann das selbe Problem wie ich.
645
Lowlevel-Coding / Re:Treiber "Management"
« am: 24. September 2010, 15:49 »
Zitat von: svenska
Das bedeutet, dass du eine Binärschnittstelle zur Verfügung stellen musst, mit der deine Treiber mit dem System reden. Linux hat das aus gutem Grund nicht - es soll Herstellern so schwer wie möglich gemacht werden, Closed Source-Treiber zu benutzen.
Das ist halt ne Philosophie-Entscheidung.

Zitat von: svenska
Falscher Ansatz - sie können unendlich viel Schaden anrichten. Die richtige Frage ist, ob du den Treibern soweit vertraust, dass sie es nicht tun.
Ich dachte mit DMA wären wir uns einig das man da leider nichts machen :(

Zitat von: svenska
Geht unter Linux ja auch, inzwischen auch automatisiert in den Distributionen. Es ist nur schwieriger.
Falscher Thread, aber egal. Ich behaupte mal genau solche Schwierigkeiten (und das ein Treiberupdate auch meisten nen Kernelupdate bedeutet) verhindern das Linux jemals bei einem Otto-Normal-Verbraucher großartig genutzt wird.

Zitat von: svenska
Legst du die Treiberschnittstelle fest, dann bist du gezwungen, sie kompatibel zu halten und (wenn sich deine Schnittstelle als unzureichend erweist) musst dann parallel mehrere dieser Schnittstellen anbieten (können). Das ist dann eine Frage der Skalierbarkeit: Bei 10 Treibern ist es egal, bei 10k Treibern essentiell wichtig. Vergleiche die frühen Linux-WLAN-Treiber (mit eigenem Stack, nur unverschlüsselt/WEP) mit den etwas späteren ("SoftMAC" WLAN-Stack, allerdings nicht in den Kernel aufgenommen) und den aktuellen ("mac80211" WLAN-Stack, im Kernel).
Ich behaupte mal das ist ne Design-Frage!? Eine vernünftig designte Schnittstelle sollte nicht verändert werden müssen (soviel zur Theorie ;) ).

Zitat von: svenska
mac80211-Treiber können (mit Ausnahmen) alle WEP, WPA, WPA2, Monitor Mode und Host Mode. Der Stack ist so primitiv (und mächtig), dass eventuelle WEP-Hardware nicht genutzt werden kann - allerdings kann dadurch jede Karte WPA2. Die Arbeit wird dem Treiber abgenommen und in der CPU erledigt.
Wenn ich das richtig verstanden habe, dann wird die gesamte Verschlüsselung in Software gemacht? Die Idee gefällt mir.
Wenn man das richtig anstellt, sollte es sogar so funktionieren, das der Treiber eventuell vorhande Hardwarefeatures nutzt und der Rest wird per Software gemacht (ungefähr wie bei OpenGL/DirectX).

Zitat von: svenska
Ich meinte: Dein Treiber sei jetzt perfekt und optimal. Dann stolpert er über nicht-perfekte Hardware.

Das eine (perfekter Treiber) widerspricht dem anderen (perfekte Hardware). Also entsteht eine Mischung aus try&error, whitelists, blacklists und Workarounds.

Damit musst du leben und wenn du dir über sowas beim Design einen Kopf machst, kann es nur leichter werden.
Ich sags mal so, wenn eine CPU irgendeinen Fehler hat (z.B. bestimmte Pentium-Bugs) und die noch nicht bekannt sind. Dann kannst du erstmal gar nichts machen, weil der Kernel nicht läuft.
Ist der Fehler dann bekannt samt nen Work-Around, kannst du diesen in deinen Kernel einbauen.

Genauso würde ich dann bei einem "perfekten" Treiber vorgehen. Hat die Hardware nen Fehler funktioniert der Treiber und damit das System nicht. Denn wenn der Fehler (wie in deinem Bsp.) in einem generischen Treiber liegt und du keinen speziellen hast, läuft dein OS halt auf der Hardware nicht. Erst wenn du nen Work-Around drin hast läuft es dann.
Sehe da jetzt nicht so das Problem. Sowas musste ich schon oft in meinem Bootloader machen, wegen irgendwelchen BIOS-Sachen, die schlecht bis gar nicht dokumentiert sind.
646
Lowlevel-Coding / Re:Treiber "Management"
« am: 24. September 2010, 14:23 »
Zitat von: svenska
Naja, ich bezog mich bei Abhängigkeiten zwischen Treiberdateien auch darauf, dass du bei ähnlicher Hardware eine gewisse Menge an "common code" hast und den wiederum als eigenen Treiber auslagerst (8390.o gemeinsam für "ne", "ne2", "ne2k-pci", "pcnet_cs", weil alles ne2000 ist). Dann hast du so eine einfache Abhängigkeit nicht mehr.
Gut, wie gesagt, ich habe noch nicht wirklich Erfahrung in der Treiber-Programmierung, aber ich würde wahrscheinlich alles dann halt doppelt und dreifach als binary-Code vorliegen haben. Das man den Source mitverwenden kann ist ja was ganz anderes.

Zitat von: svenska
Warum solltest du neue Treiber installieren?
Naja, nicht OpenSource Treiber bzw. finde ich es eher unglücklich das Treiber so sehr zum Kernel gehören, das dieser diese schon zur compile-Zeit kennen muss. Sowas will ich in meinem OS absolut nicht.
Wenn Treiber im UserMode laufen, sollte das auch besser funktionieren, da sie da nicht ganz so viel Schaden anrichten können.

Ich will jedenfalls nicht für jeden Treiber meinen Device-Server neu kompilieren müssen und ich will mir die Option offen halten, das auch andere Treiber programmieren können und das man diese nachträglich "installieren" kann ohne das etwas kompiliert werden muss.

Zitat von: svenska
Das ändert aber nichts daran, dass du dir im Datenblatt anschaust "Mensch, der sollte mit diesem/jenem Feature klarkommen, machen wir das" und nicht mitkriegst, dass vier Jahre vorher jemand anders schon festgestellt hat, dass eben dieses Feature nicht so tut wie im Datenblatt angegeben. Oder dass plötzlich ganz anderes Verhalten auftritt - an völlig fremden Stellen.
Eigentlich darf ich das jetzt nicht sagen (da ich es selbst nicht wirklich mache, gerade bei solchen Sachen nicht), aber sollte man sowas nicht dokumentieren, damit genau sowas nicht passieren kann?

Vorallem merkt man an solchen Bsp wieder mal wie sehr doch die Uni-Welt und die reale Welt auseinander sind ;)

Wäre die Welt da draußen so wie sie dir in der Uni beschrieben wird, dann würden die Leute (wenigstens innerhalb eines Unternehmens) miteinander kommunizieren und der Bug wird entweder behoben oder wird in die Dokumentation aufgenommen.

Zitat von: svenska
Und wenn du den universellen VESA-Treiber geschrieben hast, mit Unterstützung von S3 Trio32 (VBE1) bis nVidia mit Refreshsettings (VBE3), dann fällt dir eine Karte in die Hand, die behauptet, sie könne es besser als sie es kann. Und dein Treiber schlägt der Länge nach hin.
Davon gehe ich jetzt mal bei allen meinen Treibern aus. Ich lerne ja noch, da wird wohl kein Treiber perfekt werden ;)
647
Lowlevel-Coding / Re:Shared Memory
« am: 24. September 2010, 12:27 »
Zitat von: erik
Das beutet das Deine Services nicht sehr belastbar sind. Was ist wenn 5 Programme gleichzeitig aus Dateien lesen möchten? Wenn die alle im Cache im VFS wären könnte das alles parallel passieren. Stell Dir mal einen Compiler-Lauf auf einem Multi-Core-System vor, jede Compiler-Instanz möchte eine Quell-Code-Datei und einige Header-Dateien lesen (gerade die Header-Dateien dürften recht schnell im Cache liegen). Es wäre schade wenn die Compiler-Instanzen quasi serialisiert würden nur weil sie nicht parallel an die Dateien im VFS-Cache kommen.
Ich hatte das glaub ich in dem anderen Thread schonmal erklärt.

Ich habe einen allgemein bekannten Port (bzw. kann man ihn halt rausfinden) wo du dich als Client registrierst. Dann öffnet der Service nen neuen Port und über diesen wird dann kommuniziert.
Damit habe ich dann einen Port pro Prozess/Thread (je nach dem ob es sich lohnt einen Port pro Thread zu machen) und die Anfragen an diese Ports sollen serialisiert werden.
Was bei meinem Konzept eventuell nach hinten losgehen kann, sind die vielen Stacks die dadurch entstehen, aber wenn ich das richtig umsetze (und der Code, der im UserSpace ausgeführt wird, nicht alzu verschwenderisch ist) läuft das auf 8KB (4KB Kernel- + 4KB UserStack) hinaus.

Was ich mir bei deinem Konzept eher unglücklich vorstelle ist, dass du mehrere Nachrichten von ein und dem selben Prozess bekommst und alle bis auf einer deiner Popup-Threads müssen dann blockieren (da sie alle auf irgendeine gleiche Datenstruktur zugreifen). Das ist erstmal nicht so schlimm, aber wenn sie eh blockieren dann kann man alle Anfragen eines Prozesses/Threads doch gleich serialisieren und spart sich so die unnötigen Context-Switches.
Wimre wolltest du doch deine Popup-Threads so implementieren, das praktisch eine bestimmte Anzahl an Threads schon fix und fertig irgendwo rumliegt, mitsamt Stacks!? Wo ist da dann der Unterschied zu meinen blockierten Threads?

Was bei dir natürlich passieren kann ist, dass du mehrere Anfragen eines Prozesses bekommst und diese können sogar parallel abgearbeitet werden und dann vielleicht noch auf mehreren CPUs/Cores dann wird das natürlich schneller gehen als bei mir.
Aber ich will halt abwägen wo es Sinn macht einen Port pro Thread zu haben (z.B. VFS-Service) und wo es mehr Sinn macht nur einen Port pro Prozess zu haben (z.B. App-Server). Damit sollte ich auch eine gute Serilisation hinbekommen und könnte sogar sehr vernünftig C++ einsetzen.

Zitat von: erik
Wie viel Speicher das kostet kannst nur Du sagen aber für mein OS möchte ich nicht das unmengen an schlafenden Threads rumgammeln.
Seien wir mal ehrlich was wird denn dein OS die meiste Zeit machen, idlen oder? Es ist eigentlich normal das fast alle Threads/Prozesse blockieren und so gut wie keiner arbeitet.
648
Lowlevel-Coding / Re:Shared Memory
« am: 24. September 2010, 10:59 »
Zitat von: taljeth
Das bedeutet, du musst beim Portieren jeden einzelnen Aufruf von fork() patchen.
Ist das nicht genau das was ihr bei euch mit dem gcc gemacht habt oder war das was anderes?
649
Lowlevel-Coding / Re:Shared Memory
« am: 24. September 2010, 09:36 »
Zitat von: erik
Hm, also da muss ich taljeth aber doch zustimmen. File-I/O nur in ganzen Pages machen zu können dürfte schon ziemlich ungünstig werden. Mal abgesehen davon das Du damit die Möglichkeit verbaust größere Pages benutzen zu können und mit steigendem Speicherbedarf der Programme wird das auch ein steigendes Performance-Problem.
Da habe ich mich dann vielleicht ein wenig unglücklich ausgedrückt, ich meine natürlich ein vielfache von 4KB Pages, das würde dann auch große Pages wie 4MB Pages einschließen (die ich ohne hin unterstützen möchte).

Zu der Netzwerk-Geschichte. Ich seh schon, ich sollte erstmal einfach weiter mein Konzept umsetzen bzw. einfach mal anfangen ein paar wichtige Treiber (PCI-Busmanager, IDE, SATA) schreiben, damit ich sowas wie Scatter/Gather kennenlerne. Eventuell überdenke ich dann mein Konzept nochmal bzw. entwickle ein neues.
Problem bei solchen Sachen ist halt, wenn man es nicht kennt kann man es auch nicht mit einplanen.
Die meisten Probleme und Schwierigkeiten fallen einem eh erst auf wenn man es dann versucht zu implementieren oder es benutzen muss.

Zu deinen Popup-Threads. Wenn ich dich da richtig verstanden habe, wird für jede Nachricht ein neuer Thread erstellt? Das ist etwas was ich eigentlich nicht möchte, denn das läuft ja wieder auf ähnliche Probleme wie mit dem Signalhandler hinaus.
Bei meinem Konzept werden verdammt viele Threads blockieren, aber das ist ja gewollt. Ich will nicht jedes Mal nen neuen Thread erstellen (weil soviel Speicher frisst der dann auch nicht) und außerdem will ich es auf einen Thread pro Port und nicht pro Nachricht beschränken.
Bei mir werden auch verdammt viele Ports benutzt werden. Damit will ich dann das parallele Arbeiten erreichen.

Zitat von: erik
Zu bestimmen ob die erste Page kopiert werden muss ist ganz einfach indem man prüft ob der Pointer page-aligned ist. Bei der letzten Page muss man sich eben ausrechnen wo die Message zu Ende ist und dort auch prüfen ob das Ende genau auf eine Page-Granze fällt. Der einzigste Sonderfall ist wenn die Message nur eine oder zwei Pages groß ist.
Ich meinte da eigentlich was anderes. Ich bin in meinem Kopf so beschränkt ;) das ich halt Probleme habe mir vorzustellen wie man es implementiert.
Sprich man würde ne Liste mit den Pages haben, die man mappen möchte und dann noch zusätzlich ne Datenstruktur wo drin steht wo was kopiert werden muss und wo man den Buffer dafür findet.

Zitat von: erik
Der L4 ist sicher ein schönes akademisches Beispiel aber wirklich tauglich sind meiner persönlichen Meinung nach nicht alle der dort verwendeten Konzepte. Auch ich hab mir vieles über den L4 durchgelesen aber mehr als ein gute Inspirationsquelle ist er für mich nicht, schon allein deshalb weil ich Segmente mit beliebiger Größe vererben kann und nicht auf starre Page-Größen festgenagelt bin.
So mikro wie der L4 will ich meinen Kernel ja auch nicht machen, aber ist halt nen gutes Bsp. wie ein "richtiger" Mikrokernel aussehen kann.
650
Lowlevel-Coding / Re:Treiber "Management"
« am: 24. September 2010, 09:08 »
Zitat von: svenska
Die Werte würde ich übrigens im Treiber jeweils als 16bit-Werte speichern - weil es so ohnehin im Standard steht. Warum mehr? Vorteile hast du keine, Nachteile auch nicht. (Zumal du dir, wenn du eigene PCI-IDs erzeugst, möglicherweise mehr Ärger beschaffst als nötig. Und inband signalling ist sowieso ganz schlecht!)
Weil ich meistens alles zumindest auf 4byte aligne. Wenn es aber im PCI Standard Werte gibt die ohne hin nicht zugelassen sind dann kann ich die natürlich nutzen.
Ich würde so ja keine neuen PCI-IDs (wenn man es genau nimmt nur eine ;) ) erzeugen sondern einfach nur einen Wert wie z.B. 0xDEADBEEF als ne Art Konstante damit ich weis das ist ein generischer Treiber.

Zitat von: svenska
Wobei es da möglicherweise sinnvoll ist, die Treiber grundsätzlich über eine Abstraktion (z.B. der Bussysteme) zu führen - also einer API - oder (einfacher) diese Abhängigkeiten mit in die Module zu packen. "modprobe" verarbeitet jedenfalls diese dependencies, "insmod" nicht. In letzterem Fall musst du die bedingten Treiber vorher selbst laden.
Genau für sowas macht sich mein Konzept ganz gut. Ich bin mir gerade zwar nicht sicher das wir vom selben Thema sprechen aber egal.
Ich wollte diese Abstraktion von Bussystemen auf jeden Fall machen (zumindest ISA/PCI/USB) und die Abhängigkeiten (die ich momentan sehe, kann sein das dann doch noch andere hinzu kommen) lösen sich von ganz alleine. Denn wenn kein PCI-Busmanager geladen und gestartet ist, werden die anderen Treiber auch nicht benötigt, da noch gar keine Geräte vorhanden sind.

Zitat von: svenska
Treiber werden aber grundsätzlich nur geladen, wenn die entsprechende Hardware auch vorhanden ist - das ist bei Linux so.
Ok, das wusste ich nicht. Aber wie funktioniert dann das installieren eines neuen Treibers? Muss der Kernel dann neu kompiliert werden oder wird der Treiber in irgendein Bootskript eingetragen und wird mitgeladen auch wenn er vielleicht gar nicht benötigt wird?

Zitat von: svenska
Oder du lässt die Module von deinem Multiboot-Bootloader mitladen, allerdings müsstest du dann die Konfiguration jeweils an das System anpassen.
Naja, ich wollte dann meinen Loader alle wichtigen Treiber (so fern vorhanden) laden lassen (PCI, USB, IDE, SATA, USB-MSD). Ob das dann auch so klappt oder ich das nochmal über den Haufen werfen muss, werd ich dann sehen.

Zitat von: svenska
Zu dem Video: Bedenke, dass das in dem Code nur subtile Bugs waren, die eventuell auch nur auf bestimmten Revisionen funktionieren. Und, dass der relevante Abschnitt in einer/zwei von hunderten Codezeilen steckt - versteckt in Code, der eine Hardware mit/ohne Datenblatt korrekt ansteuern muss. Da passieren Fehler. Wenn du behauptest, du kriegst das besser hin, dann enttäusche ich dich unbesehen.
Ich habe schon wirklich schöne Bugs produziert, vorallem finden sich meine Bugs immer so schwer (weil ich sie immer an der falschen Stelle vermute).
Aber was da manchmal gemacht wurde ist ein "try&fail"-Verfahren. Vorallem fand ich es gut, wenn man einen Patch dann wieder rückgängig macht und der Fehler ist wieder da ;)
Zumal das ja teilweise Code von den Leuten war die die Dokumentation haben müssten (z.B. Intel bei ihrer eigenen Hardware).
651
Lowlevel-Coding / Re:Shared Memory
« am: 23. September 2010, 19:26 »
Zitat von: erik
Natürlich kann FlashBurn native Funktionen nach eigenen Geschmack bauen wie er will aber wenn er wirklich ein read baut das einen Pointer zurück gibt dann weicht er damit so weit vom üblichen Weg ab das er daraus kaum einen Nutzen ziehen kann (wenn er Programme portieren möchte und diese dann sein natives API benutzen sollen würde er große Teile dieser Programme komplett neu schreiben müssen).
Das ist jetzt etwas mit dem ich nicht gerechnet hätte ;)

Ich gehe darauf jetzt mal ein. Sagen wir mal die meisten OpenSource Programme findest du im Linux/Posix Bereich. Dann würde das heißen, das man nur noch Posix kompatible Systeme schreiben sollte und damit kommt es effektiv zu einem Stillstand!

Mein Punkt ist, das wenn man etwas neues/anderes/besseres machen will, muss man leider bestimme Sachen neu schreiben!

Wenn man danach geht, müsste ich mein System auf fork und co aufbauen. Was ich aber nicht mache.

Im Endeffekt implezierst du damit, das gerade Hobby OSs eigentlich nur ein Rewrite von Linux sein könnten.

Zitat von: taljeth
Naja, was ist, wenn du nur einen Teil eines (schon vorhandenen) Objekts/Puffers einlesen möchtest?
Sorry ich versteh die Frage nicht bzw. was du meinst :(

Zitat von: taljeth
Aber selbst wenn du neue Objekte haben willst, die aber langlebig sein sollen, wäre es wahrscheinlich ein bisschen übertrieben, jedem davon eine komplette Page zuzuweisen.
Richtig. Wir waren ja aber insbesondere bei Dateien und dem HDD-Treiber und da finde ich mein Konzept nicht so fehl am Platz.
Bei Netzwerk-Sachen sieht das leider schon wieder anders aus. Da würde ich das Ganze wahrscheinlich durch eine Pipe jagen. Das wäre dann wieder kein zero-copy, sondern 2x Copy, aber gerade beim Netzwerk-Zeugs muss doch eh kopiert werden (um die eigentlichen Daten vom Protokoll zu trennen, oder?).

Zitat von: erik
Wenn ich Dich weiterhin so gut überzeugen kann dann baust Du am Ende auch noch ein IPC-System das auf PopUp-Threads bassiert.
Naja, sowas ähnliches habe ich ja eh geplant ;)

Bei mir würde nicht jede Nachricht nen neuen Thread aufmachen, sondern jeder Port würde durch einen Thread bearbeitet werden (was natürlich kein muss ist).

Zitat von: erik
Dann hast Du entweder ein kleines Sicherheitsproblem oder Du musst maximal 2 Pages doch kopieren (aber nur auf der obersten Ebene zur eigentlichen Applikation, alle anderen Ebenen darunter können immer ohne kopieren auskommen, einmal kopieren reicht schließlich).
Ok, ein Sicherheitsproblem der Größe möchte ich dann nicht.

Sorry, wenn ich jetzt wie ein dummer Newbie klinge, aber wie du dir das mit dem kopieren von max 2 Pages (den "Randpages") vorstellst müsstest du mir mal ganz genau erklären.

Ich könnte mir nur vorstellen, das du, außer bei den beiden Randpages, immer direkt in den Speicher des Clienten schreibst und für die beiden Randpages allokierst du Speicher, schreibst da die Daten rein und lässt die Daten aus diesen beiden Pages dann in die Randpages des Clienten kopieren. Soweit richtig?

Bei mir hapert es jetzt an der Umsetzung, sprich wie man sowas machen könnte.

Zitat von: erik
Ich denke mal das Abquatschen zwischen Client und Service läuft weiterhin über IPC ab und das Erstellen des virtuellen Speichers beim Client erfordert eben für beide Seiten einen zusätzlichen Syscall, erst muss der Service das vorbereiten und einen Handler registrieren und dann kann der Client, mit einer extra ID/Handle o.ä. (in der Antwort beim IPC-Vorgang enthalten), diesen Speicher einbinden und bekommt einen Pointer in seinen virtuellen Adressraum.
Mein Lieblingsbsp. ist hier der L4. Der bietet wirklich außer IPC und Thread-Management nicht viel mehr an (soweit ich es verstanden habe, bzw. habe ich nichts dazu gefunden). D.h. auch kein Mapping von Speicher in andere Prozesse, was er anbietet ist das "Versenden" von ganzen Pages als Nachrichten.
Eventuell kommt auch genau daher mein denken, du als Treiber versendest die Daten (daher bekommt man einen Pointer zurück).
652
Lowlevel-Coding / Re:Shared Memory
« am: 23. September 2010, 18:37 »
Zitat von: taljeth
FlashBurns native Funktion könnte ja anders aussehen.
Im Moment glaube ich, um mir die Sache einfacher zu machen, würde ich als native Funktionen nur komplette Pages durch die Gegend schieben. D.h. fread müsste sich die Daten dann daraus kopieren in den Buffer des Clienten.
Das ist aber nur eine Idee!

Zitat von: taljeth
Was natürlich nichts dran ändert, dass eine Funktion, die einen neuen Puffer zurückgibt, für viele Sachen nicht so richtig gut geeignet ist...
Ich gehe mal davon aus, das du mehr Erfahrung in der Anwendungsprogrammierung hast als ich (was nicht besonders schwer ist).
Aber warum ist das nicht so gut geeignet?

Zitat von: erik
Warum benutzt der HDD-Treiber ein Aligment? Dafür gibt es doch gar keinen Grund.
Grund wäre das ich noch nie so einen Treiber geschrieben habe ;)

Ich dachte halt das es so abläuft, das der VFS-Service nen "Auftrag" an den HDD-Treiber gibt bestimmte Sektoren zu laden und er bekommt entweder die Pages mit den Sachen zurück oder nen Fehler. So in der Art:
void *loadLBA(uint64t lba, uint32t count)
Das ist halt meine Weise "zu denken".

Zitat von: erik
Lesen ist wenn der Client Speicher hat (egal ob per malloc auf dem Heap oder auf dem Stack-Frame oder als normales statisches Array) und möchte das dort irgendwelche Daten rein gelegt werden. Wenn wir mal kurz die Ränder außer Acht lassen dann wird der Speicher für die Dauer des gesamten (aber kurzen) IPC-Vorgangs zusätzlich auch in den passenden Service gemappt, dort befüllt und zum Schluss beim Service wieder freigegeben. Im Client war dieser Speicher die ganze Zeit normal anwesend. Nachdem das fread damit fertig ist kann die Applikation mit dem Speicher bzw. den Daten darin machen was sie will.
Klingt erstmal super!

Mein Problem damit wäre, wenn wir die Ränder mal nicht außer acht lassen, dann würde ich das per SharedMemory in den Treiber mappen. Also könnte der Treiber Daten aus dem Client lesen (nagut er könnte sie so oder so überschreiben, also wäre das egal, obwohl wenn da Passwörter stehen und das der Ethernet-Treiber wäre?). Ich habe einfach ein Problem mit dem Mappen des Buffers des Clienten in einen Treiber ohne das der Treiber die Daten des Clienten lesen kann und ohne das ich mir was anderes als SharedMemory dafür einfallen lasse.

Zitat von: erik
Bei richtigem File-Mapping wird eine Datei in den Adressraum der Applikation eingeblendet und der Service registriert sich als eine Art Page-Fault-Handler für diesen Bereich und managed so dass Lesen der Daten von HDD in den Speicher der Applikation wenn zum ersten mal auf eine bestimmte Page zugegriffen wird. Dieser Speicher wird aber eben von einer bestimmten Funktion in einer User-Mode-Library in der Applikation (welche dann eben spezielle Syscalls benutzt) zur Verfügung gestellt und kann daher immer passend ausgerichtet sein. Wenn man eine so gemappte Datei wieder schließen möchte dann muss der Service alle modifizierten Pages auf die HDD zurückschreiben, meldet seinen Page-Fault-Handler ab und danach kann dann der spezielle Speicher in der Applikation wieder freigegeben werden.
Interessant! Ich will/muss mich ja nicht gleich damit beschäftigen, aber ich mache mir gerade Gedanken wie man das mit dem PageFault-Handler löst, aber wie du schon geschrieben hast, dafür benötigt man dann noch Syscalls.
Aber wie machen sowas richtige Mikrokernel die außer IPC nicht viel mehr anbieten?
653
Lowlevel-Coding / Re:Shared Memory
« am: 23. September 2010, 15:20 »
Zitat von: erik
Also ich würde schon sagen dass das mit "nur den Rand kopieren" recht zufriedenstellend ist, besser geht es eben nur mit Paging nicht.
Ich weis das es nicht gerade deine lieblings Aufgabe ist ;) aber ich habe da so meine Verständnis Probleme und wenn die weg sind, könnte ich mich fast zu einem dynamic-size IPC hinreißen lassen.

Also ich habe folgendes Problem:

Client will 10000bytes aus einer Datei gelesen bekommen, erstellt den Buffer über malloc und der hat die Adresse (die virtuelle bei ihm im AdressSpace) 0x1000200.
Der HDD-Treiber lädt die Datei aber 4KB align in den Speicher, also z.B. 0x4000000.
Wenn ich die Daten jetzt mappen wollte, dann geht das aber nicht, da ja der PageOffset beim Clienten 0x200 ist und beim Treiber 0x0. Die Daten sind also "verschoben" oder unausgerichtet und daher geht das Mappen (nach meinem Verständnis) nicht und es muss kopiert werden.

Ich denke mal das ich da irgendwas nicht richtig verstanden habe, denn irgendwie muss das ja funktionieren.
654
Lowlevel-Coding / Re:Treiber "Management"
« am: 23. September 2010, 15:03 »
Zitat von: erik
Das beste was ein OS tun kann ist, wenn es für die Treiber von virtuell an physisch umrechnet, möglichst genau hinzuschauen ob der Treiber auf die virtuellen Adressen überhaupt zugreifen darf.
Naja, das ist das was ich machen will, löst das eigentlich Problem aber nicht wirklich, denn der Treiber kann noch immer hinschreiben wo er lustig ist.

Zitat von: erik
Für die Product/Vendor-IDs sind IMHO 0x0000 und 0xFFFF verboten (eventuell nur wenn Vendor-ID == Product-ID ist) und es gibt auch ungültige Class-Codes, wenn Du das genau wissen möchtest musst Du in die PCI-Spec schauen (wenn Du möchtest kann ich das heute Abend mal machen), aber sauber ist dieser Weg meiner Meinung nach nicht.
Naja, das ist doch genau sowas was ich gesucht habe, aber da ich eigentlich schon die IDs auf 32bit erweitern wollte (die 6bytes sind dann auch nicht so schlimm) ist das eigentlich auch egal.
Was gefällt dir daran nicht bzw. denke ich mal du siehst da irgendwo ein Problem?

Zitat von: erik
Bei Windows ist die Registry die Datenbank und was da nicht drin steht wird auch nicht zu booten benutzt, erst wenn der User Windows anweist einen neuen Treiber zu suchen (bzw. Windows den User frag ob es nach einem neuen suchen soll) kommt auch ein neuer Treiber in die Registry und wird auch erst nach dem nächsten Boot aktiv.
Das ist genau das was ich auf keinen Fall haben will. Mir hat die Idee immer gefallen, das du dein USB-Stick, mit dem OS darauf, nimmst und an nen anderen PC steckst und schon läuft das OS ohne das es Probleme gibt (das z.B. der Treiber nicht in der Registry steht oder nicht im Bootscript steht oder nicht in den Kernel kompiliert ist).

Zu dem Thema passt doch eigentlich ne LiveCD auf Linux-Basis. Wie wird das dort gemacht? Sind da alle Treiber in irgendeinem Skript eingetragen (denn im Kernel sind die ja nicht mehr, sondern als externe Module)?

Was so auch noch nicht gemacht wurde (außer vielleicht bei Windows, da ist es in den INF-Dateien) das die Treiber nicht nachgucken ob ein Gerät für sie vorhanden ist (das wird bei Linux, möchte ich meinen, noch so gemacht) sondern das der Treiber auch nur geladen wird, wenn ein Gerät für ihn vorhanden ist.
Damit kann man einiges an Zeit einsparen (denke ich doch). Zumindest sollte sich der Bootvorgang so wesentlich beschleunigen lassen.
655
Lowlevel-Coding / Re:Shared Memory
« am: 23. September 2010, 14:37 »
Zitat von: erik
Sorry, aber Zero-Copy sehe ich in Deinem Konzept nicht. Was nicht heißt das ich Dein Konzept auch sonst wie schlecht finde, es ging mir heute nur um das Zero-Copy.
Ich denke wir sollten uns darauf einigen, das es unter Paging kein "immer zero-copy möglich" gibt! Man macht halt das beste daraus.

Zitat von: erik
Das deckt sich aber nicht mit fread (das bekommt einen Pointer wo die Daten hin sollen und liefert nicht einen Pointer zurück wo das System die Daten hingelegt hat) und auch sonst keinem der üblichen SW-Paradigmen, da wirst Du wohl viel kopieren müssen in Deiner libc.
Naja, bei nem Mikrokernel der mehr mikro ist als das was man heute als solche bezeichnet (z.B. Haiku) wird man um einiges an kopieren nicht vorbei kommen.

Wie gesagt, sehe ich auch mit Paging-Tricks, wie dem reinmappen und nur den Rand kopieren, nicht das man das irgendwie "zufriedenstellend" lösen könnte.

Zitat von: erik
Bis auf das Datei-Mapping (was auch was völlig anderes als fread/fwrite ist) geht alles bei mir über den selben Mechanismus, egal ob nur 3 Bytes oder ganze 3 GBytes, egal ob ausgerichtet oder nicht.
Nicht dass das hierher gehören würde, aber mich würde mal interessieren wie du folgendes löst.

FILE *file= fopen("foobar","r");
char buffer[512], *ptr= &buffer;

for(uint32t x= 0; x < 512/4; x++) {
 fread(ptr,sizeof(uint32t),1,file);
 fseek(file,12,SEEK_CUR);
 ptr+= sizeof(uint32t);
}
Mir geht es bei diesem (sinnlosen??) Bsp darum, dass du ja immer den Speicher mitgibts wo die Daten reinsollen, wie bekommst du aber die Daten aus dem Sektor, der zu der Stelle in der Datei gehört, ohne kopieren in den Buffer?
656
Lowlevel-Coding / Re:Treiber "Management"
« am: 23. September 2010, 13:21 »
@erik

Andere Idee  :-D

Was wäre wenn man DMA über die MMU (sowas wie ne IOMMU gibt es ja bei AMD schon, ob dass ungefähr das ist was ich meine weis ich aber nicht) laufen lassen würde. Sprich du initialisierst den DMA Kontroller mit dem PageDir (also den Wert von CR3 des Treibers, der sollte sich eigentlich nicht ändern) und dann übergibst du immer die virtuelle anstatt der physischen Adresse? Würde das nicht alle Probleme lösen und trotzdem alles andere wie gewohnt zulassen?

Zitat von: erik
Was genau ist das Problem? Du findest ein PCI-Gerät und holst die Vendor/Product-IDs und den Class-Code und durchsuchst damit erst das Array mit den spezifischen Treibern, anhand Vendor/Product-ID, und danach (falls nichts spezifisches gefunden wurde) das Array mit den generischen Treibern, anhand des Class-Code.
Das Problem ist, wie erstellst du das Array mit den generischen Treibern, wenn man diese nur anhand der IDs bestimmen kann.
Ich wollte eine Struktur für beide Arten von Treibern und wenn es da keinen Wert für die VendorID gibt, der laut PCI Specs nicht zugelassen ist, dann hast du nur spezielle Treiber, erweitere ich aber die VendorID auf 32bit, kann ich Werte haben die nicht zugelassen sind und kann so meine generischen Treiber erkennen.

Zitat von: erik
Das gilt IMHO auch für die generischen Treiber, auch hier sollte es nicht möglich das mehrere Treiber für ein und den selben Class-Code zuständig sind.
Ich weis nicht ob wir jetzt von der selben Sache reden, aber was ist mit einem IDE Treiber für Intel-Chipsätze, einem für SIS-Chipsätze usw. die haben alle den selben Class-Code und werden erst über den Vendor bestimmt.
Selbe für Grafikkarten, die haben alle den selben Class-Code, nur andere VendorIDs.
Selbst unter Windows kann man mehrere Treiber für ein und das selbe Gerät haben, es wird halt immer nur einer genutzt (der dann in der Registry eingetragen ist).
657
Lowlevel-Coding / Re:Shared Memory
« am: 23. September 2010, 13:08 »
Zitat von: erik
Das sehe ich noch nicht, solange die Clients sich extra neuen Speicher holen müssen (weil dieser ja wegen dem IPC weggenommen wird) und ihn extra mit Daten befüllen müssen (also kopieren) nur um IPC machen zu können bist Du IMHO noch nicht bei Zero-Copy! Oder habe ich was übersehen?
Außerdem sehe ich da eine Menge Syscalls für die Clients: Speicher holen, IPC antriggern, Speicher mitgeben, Antwort abholen und eventuell noch Speicher zurückholen.
Um es mal am Bsp. des HDD-Treibers zu "zeigen".

Du musst Speicher holen damit der HDD-Kontroller weis wo er die Daten hinladen soll (das wirst du bei dir wohl auch machen müssen).
Hat er die Daten dann in diesen Speicher geladen, wird er mit einem Syscall per Nachricht zum VFS-Service geschickt.
Wie dieser dann die Daten an den Clienten weiterreicht ist erstmal unwichtig, denn da müsste man viele Fälle betrachten (nur wenige Bytes, eine ganze Datei, die gemappt werden könnte, ...).

Ich denke du versuchst dein IPC auf mein IPC abzubilden ;)

Bei meinem IPC schickst du keinen "Speicher" mit wo die Daten reinkommen, du bekommst ihn und das RPC bei mir auch mit einem Syscall gemacht wird, weist du ja eigentlich.
658
Lowlevel-Coding / Re:Shared Memory
« am: 23. September 2010, 10:46 »
Zitat von: bluecode
Um virtuellen Speicher zu allozieren muss man nicht in die PageTables schauen. Dafür wird man wohl sowieso andere geeignete Datenstrukturen verwenden, z.B. Buddy. Es läuft doch niemand (zumindest hoffe ich das) wie bei einer Bitmap durch die PageTables und sucht nach einem passend großen Stück virtuellen Speichers...
Ich benutze weder Buddy noch gehe ich die PageTables durch, aber wie gesagt, diese Datenstrukturen sind Prozessbezogen und nur dann "sichtbar" wenn der Prozess auch läuft. Man kann auf diese Daten nicht von einem anderem Prozess aus zugreifen.

Zitat von: bluecode
Der Fall tritt ja schon allein, weil es nur ein Hobby-OS ist, wohl eher nicht auf. Oder werden da fette Datenbanken oä. auf der 32Bit Version laufen.
Auch hier wieder, nur weil es auf einem HobbyOS unwahrscheinlich ist/erscheint, sollte man den Fall trotzdem "bearbeiten" können.
659
Lowlevel-Coding / Re:Shared Memory
« am: 22. September 2010, 21:31 »
Zitat von: erik
Warum sollte das nicht gleich der SendMSG-Syscall machen?
Naja, wird schwierig, weil zusätzliche Parameter (die bei den meisten Aufrufen total Sinnlos wären) und wie gesagt macht sich das über nen eigenen Syscall einfacher (zumindest die Idee die ich gerade im Kopf dazu habe).

Zitat von: erik
Der Syscall soll doch nur so lange blockieren bis das ummappen erledigt ist, so lange wird das schon nicht dauern.

Das ist aber auch nicht gerade höflich wenn Speicher einfach so verschwindet. Was ist wenn der Client es noch mal probieren will? Dann muss er neuen Speicher allozieren und neu mit Daten befüllen, das stelle ich mir unpraktisch vor.
Ich habe mir das nochmal genau überlegt, an und für sich, fordert der Client ja den Speicher an, d.h. er weis wie groß der Bereich ist, soll heißen er wird das nur machen wenn er auch genug freien virtuellen Speicher hat.
Daher kann man sagen, das der Fall das es nicht gemappt werden kann eher selten bis gar nicht auftreten sollte (was man aber bei Multithreading nicht so einfach sagen kann).
Was das Blockieren betrifft, das sollte (unter den selben Betrachtungspunkten wie Oben, sprich der Client wartet darauf) eigentlich auch nicht lange dauern (wie du schon sagtest).

Sprich ich werd es trotzdem mit nem Flag machen, das der Sender nicht blockiert und ich werde nen eigenen Syscall dafür machen (ist einfach einfacher ;) und performanter).

Jetzt komme ich dem zero-copy immer näher ;)
660
Lowlevel-Coding / Re:Shared Memory
« am: 22. September 2010, 19:19 »
Zitat von: erik
also ich würde in dem Sende-Syscall erst den Speicher ins Ziel mappen und danach erst beim Sender unmappen. Wenn das mappen beim Ziel nicht klappt dann kommt der Syscall mit einem Error-Code zurück und der Speicher ist noch beim Sender.
Wenn ich das als eigenen Syscall machen (also nicht über den sendMsg Syscall) dann dürfte das selbst bei meinem IPC System hinzubekommen sein.

Problematisch ist halt nur, dass das ganze dann halt blockierend wäre, was ich eher unschön finde, aber das könnte man ja über ein Flag lösen!

Zitat von: erik
Physischer Speicher ohne Besitzer ist IMHO ein Bug im Kernel.
Da hast du mich dann nicht ganz verstanden, wenn der Speicher nicht gemappt werden konnte, wird er einfach freigegeben als wenn es ihn nie gegeben hätte ;)
Seiten: 1 ... 31 32 [33] 34 35 ... 43

Einloggen