Autor Thema: Implementation von RPC  (Gelesen 11698 mal)

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« am: 10. April 2007, 18:53 »
Ich hab mir in den letzten 2 Wochen mal Gedanken zu RPC gemacht und heute eine Implementierung für mein OS geschrieben. Meine Implementierung sieht (mal alle lightOS spezifischen Details weggelassen so aus): Ein thread registriert einen RPC-Handler, welcher von anderen Threads aufgerufen werden kann. Sobald ein RPC-Aufruf reinkommt wird der Registerinhalt des threads, welcher den RPC-Handler registriert hat, gespeichert, ein paar Parameter auf den Stack gepusht und dann beim RPC-Handler mit der Ausführung begonnen. Ist der RPC-Handler fertig werden wird der alte Registerinhalt wiederhergestellt und mit der Ausführung an der alten stelle weitergemacht. (das ist afaik mit der LOST IPC vergleichbar)
Nun hab ich folgendes Problem: Es gibt in jedem Thread bestimmte Bereiche, die atomisch ausgeführt werden müssen, zB best. Teile von malloc, das pushen auf einen vector, das anhängen an eine Liste, etc... Da diese Sachen nicht innerhalb von einer Instruktion geschehen, könnten sie von einem RPC-Aufruf unterbrochen werden. Wenn jetzt aber der RPC-Handler seinerseits eine dieser Funktionen aufruft, dann könnte es krachen, zB könnten Speicherbereiche doppelt alloziert werden, freie Speicherbereiche verloren gehen oder der Zustand der Liste/des Vectors inkonsistent werden. In multithreading anwendungen würde man das über mutex/futex, Semaphore oder Semaphoren regeln, aber das geht in diesem Fall nicht, da bei allen diesen Synchronisationsmethoden die möglichkeit bestehen muss, dass der Codebereich, welcher den Lock hat, solange ausgeführt werden muss, bis dieser Lock wieder frei ist. Da aber der RPC-Handler die weitere Ausführung unterbrochen hat und erst nach dem RPC-Handler die Ausführung dort weitergeht, können oben genannte Methoden nicht verwendet werden ohne das es nicht zu einem Deadlock kommt.
Die einzigen Lösungen die ich sehe:
* spezielle Bereiche des Threads RPC'bar bzw. der umgekehrte Fall nicht-RPC'bar machen => viel Aufwand, portierbarkeit von bestehendem Code?
* RPC-Handler nichts derartiges machen lassen => schränkt zu sehr ein
* Popup-Threads: Für jeden RPC-Call einen Thread erstellen bzw. einen eigenen bestehenden Thread weiternutzen. Dann kann man solche Probleme wieder über die ganz normale Synchronisation von Multithreadinganwendungen lösen.
* Thread Migration: fast das gleiche wie Popup-Thread. Der unterschied ist nur, dass man den aufrufenden thread in den Kontext des aufzurufenden Prozesses verschleppt und dann den RPC-Handler ausführt. Damit spart man sich die Kosten der Threaderstellung, aber dadurch wird die RPC wieder synchron.

Mir gefallen die ersten beiden Lösungen überhaupt nicht und die letzten beiden kann man nunmal auch über message-passing und multithreading lösen ohne soviel aufwand betreiben zu müssen. Fällt evtl. jemandem noch eine andere Lösung ein, wie man RPC realisieren könnte?
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

Korona

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 12. April 2007, 02:45 »
Ich verstehe das Problem nicht ganz.

Thread A registriert einen RPC Handler. Was macht der dann? Blockieren bis ein RPC Call kommt oder einfach weiterlaufen? Jetzt ruft Thread B den RPC Handler auf. Thread A wird unterbrochen und begint mit Abarbeitung des RPC Handlers. Wenn Thread A dadurch bei kritischen Aktionen unterbrochen wird, könnten Konflikte auftreten. Verwende doch einfach ein Lock/Mutex/Semaphore und lass Thread B vor dem RPC Call solange blocken bis Thread A den kritischen Bereich verlassen hat?

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #2 am: 12. April 2007, 13:52 »
Verwende doch einfach ein Lock/Mutex/Semaphore und lass Thread B vor dem RPC Call solange blocken bis Thread A den kritischen Bereich verlassen hat?
Das ist mehr oder weniger die erste Lösung. Und wie ich oben schon geschrieben hab ist es sehr viel Aufwand nach jedem noch so kleinen Konflikt zu suchen, da solche Konflikte ja nicht immer offensichtlich sind.

Aber vielleicht hätt ich deutlicher sagen sollen, was genau ich mit rpc vorhab: Momentan verwende ich message-passing als ipc. Die messages werden an einen port gesendet. Ein Thread kann nun warten bis auf einem best. Port eine message ankommt. Leider wäre es oft geschickt, wenn man neben dem warten auf einen port auch noch auf anderen Ports messages entgegen nehmen könnte. Da wäre nun rpc ins spiel gekommen. Ich hätte/hatte es bereits so implementiert, dass ein thread auch einstellen kann, das bei einem best. port bei einer message ein rpc gemacht wird. Das bedeutet aber, dass rpc bei mir generell nur bei mehreren Sachen die gleichzeitig von einem thread übernommen werden müssen, benutzt werden würde. Da wär es mir persönlich zuviel Aufwand jedesmal nach allen Konflikten zu suchen und beim Debuggen würden diese Konflikte wenn nicht erkannt, zu nicht reproduzierbaren Fehlern führen.
Deshalb bau ich das message passing lieber so um, dass ein thread auf mehrere Ports gleichzeitig warten kann.
Insofern hat sich das mehr oder weniger sowieso erledigt.
btw. LOST verwendet die erste Lösung, falls es interessiert.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

Korona

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 13. April 2007, 18:20 »
In meinem OS läuft die IPC über "Streams" ab. Ein Task kann einen "Server" bereitstellen, zu dem sich ein anderer Task "verbinden" kann. Die Kommunikation läuft über Shared Memory ab, 2 Buffer (einer pro Richtung: Server - Client und Client - Server) werden in beide Prozesse gemappt. Der Server-Task wartet (blockiert) in einem Thread auf eingehende Verbindungen und erstellt für jede Verbindung einen neuen Thread. Dieser Thread wartet (blockiert) dann auf Nachrichten an sein jeweiligen Stream, verarbeitet diese und schickt das Ergebniss zurück. Locks müssen nur beim Lesen und Schreiben in/aus Streams verwendet werden, damit die Daten in den Buffern und die Offset Felder, welche die momentane Lese/Schreib-Position inhalb der Buffer angeben konsistent bleiben. Dieses Modell hat gegenüber normalem Messagepassing den Vorteil, das es weniger Systemcalls benötigt und die Kommunikation schneller abläuft.

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 13. April 2007, 18:34 »
OT: Solche Beschreibungen hätten übrigens sehr gut Platz im Wiki...damit hätten solche, die bald selber ein IPC coden wollen gute Inspiration dafür...

Gruss
Nooooooooos

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #5 am: 13. April 2007, 19:06 »
Dieser Thread wartet (blockiert) dann auf Nachrichten an sein jeweiligen Stream
Hast du einen Stream pro thread? Oder kann ein thread auch mehrere haben? Kann ein thread auch auf mehrere warten?
Hat dein OS einen Namen und eine Homepage/svn/whatever?

Nos: Habs auf meine TODO-Liste fürs wiki. Die ist aber sowieso schon lang ^^ Und mir ist es momentan ehrlich gesagt wichtiger die Zeit in mein OS zu stecken. Falls du Probleme hast kannst ja auch die anderen bzw. mich im IRC fragen, die meisten sind ja fast immer online.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 13. April 2007, 19:23 »
Hehe sicher...ich dachte nur wenn jeder seine Art von IPC beschreiben würde, wäre damit wieder ein schöner Teil an der Wissens-Datenbank geschaffen.
Du könntest diese ToDo Liste eigentich auch irgendwo ins Wiki schreiben...Dann könnten auch mal andere wenn sie Zeit und Lust haben daran etwas machen...

Gruss
Noooooooooos

Korona

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 14. April 2007, 19:24 »
Mein Os hat einen Namen: managarm
SVN oder Homepage gibts allerdings noch nicht, das wirds erst in ein oder zwei Monaten geben, wenn man etwas damit anfangen kann (einen Texteditor mit GUI benutzen etwa).

 

Einloggen