amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > Messages senden ohne Forbid(); [ - Suche - Neue Beiträge - Registrieren - Login - ]

-1- [ - Beitrag schreiben - ]

11.08.2003, 17:39 Uhr

Geri
Posts: 138
Nutzer
Hallo!

Ich habe eine Frage zum Message-(IPC)-System von Exec. Normalerweise wird zum Senden einer Message zuerst Forbid() aufgerufen, um das Multitasking mehr oder weniger abzuschalten, dann der Port des anderen Programms gesucht (FindPort()) und die Nachricht an das Programm mit PutMsg() oder ähnlichem gesendet. Zuletzt wird das Multitasking mit Permit() wieder "erlaubt".
Soviel zur Theorie... :sleep:

Nun wurde aber oft betont, dass man Forbid(), Permit() (und vielleicht auch Disable()) etc. in Zukunft nicht mehr verwenden sollte, da es natürlich nicht sehr schön ist das Multitasking einfach abzuschalten, was besonders auf einem AmigaOne Dual-G4 :lickout: zu drastischen Geschwindigkeitseinbußen führen sollte/kann. ;(

Nun zu meiner Frage: Ist es möglich mit Semaphoren auch schon unter OS3.x auf die Forbid() und Permit() Befehle zu verzichten, ohne dass die Nachrichten irgendwo im Nirvana verschwinden oder es zu einem Deadlock kommt (schließlich sollte die Nachricht ja immer zurückgesandt werden mit ReplyMsg()). Hat jemand vielleicht ein Codeexample dafür?

Danke schonmal für eure Eingebungen! 8)

Geri

--
--
Southtyrolean Amiga user since 1989!

[ - Antworten - Zitieren - Direktlink - ]

11.08.2003, 18:59 Uhr

Holger
Posts: 8116
Nutzer
Die Frage ist eher, was Du eigentlich genau machen willst.

FindPort() benutzt man um öffentliche Ports anhand ihres Namens anzusprechen. Je nachdem, warum Du auf dieses Mittel zurückgreifen willst, gibt es auch eine andere Antwort.

Wenn es zum Beispiel um ARexx-Nachrichten geht, kann man die rexxsyslib.library benutzen, um mittels LockRexxBase() die öffentlichen Ports vor Veränderungen während der Operation zu schützen. Das funktioniert aber nur, wenn das andere Programm sich auch sauber daran hält und eben nicht mittels Forbid()-Permit() Aufrufen und direkten Manipulationen arbeitet.

Für die meisten Anwendungen gilt allerdings: Wenn Du eine Möglichkeit hast, den Besitzer des Ports nach einer Semaphore zu fragen, dann gibt es eigentlich auch keinen vernüftigen Grund mehr, den Port über FindPort() zu suchen zu müssen.

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

12.08.2003, 09:27 Uhr

Geri
Posts: 138
Nutzer
Gedacht war es für ein (Client-)Server Programm (C/C++) das möglichst ohne viel CPU-Zeit im Hintergrund laufen sollte. Da aber in kurzer Zeit immer sehr viele Nachrichten anfallen würden, hätte ich das gerne systemfreundlicher, also ohne Forbid() und Permit() gelöst. Das Server-Programm hätte außerdem kompatibel zu einem bereits existierenden Programm sein sollen, das allerdings Forbid() und FindPort() ausgiebig zur IPC nutzt.


Für die meisten Anwendungen gilt allerdings: Wenn Du eine Möglichkeit hast, den Besitzer des Ports nach einer Semaphore zu fragen, dann gibt es eigentlich auch keinen vernüftigen Grund mehr, den Port über FindPort() zu suchen zu müssen.


Eine eigene Semaphore die von einem Client "besetzt" werden kann ist eine Lösung. Dabei geht jedoch die Kompatibilität zu den alten Client-Applikationen verloren.
Allerdings würde ich den öffentlichen Port nur mehr für dia alten Applikationen benötigen und die neuen könnten sich über die Semaphore mit dem Server synchronisieren. Sehe ich das richtig?

Geri

--
Southtyrolean Amiga user since 1989!

[ - Antworten - Zitieren - Direktlink - ]

12.08.2003, 11:06 Uhr

Inferno
Posts: 157
Nutzer
Hallo Gery,

wenn ich das richtig verstehe, brauchst Du Forbid/Permit NUR für FindPort, nicht aber für das Message-Versenden. Das Problem ist hier, daß das System die Forbid/Permit-Statements braucht, damit nicht ein anderer Prozess darauf zugreift. Das Problem kannst Du aber recht einfach lösen:

Alle Clients fordern den Port EINMAL an (beim Programmstart) d.h. Du mußt einmal in den sauren Apfel beißen. Den Pointer speicherst Du dann in einer Variable und nutzt diese dann bei allen Message-Sende-Aufrufen OHNE Forbid/Permit (und natürlich auch OHNE FindPort).

Gruß,

Inf.

[ - Antworten - Zitieren - Direktlink - ]

12.08.2003, 12:41 Uhr

Geri
Posts: 138
Nutzer
Zitat:
Original von Inferno:
Hallo Gery,

...Das Problem ist hier, daß das System die Forbid/Permit-Statements braucht, damit nicht ein anderer Prozess darauf zugreift...


Klar! Das System muß z.B. verhindern, dass ein Task seinen Port schließen kann wenn ein anderer Task ihm eine Nachricht sendet. Wird der Port "gleichzeitig" geschlossen, kann der andere Task ewig auf seine Antwort warten, die (soviel ich weiß) immer gesendet werden muß (mit ReplyMsg()). Die Folge wäre ein Deadlock!!! :nuke:

Zitat:
Alle Clients fordern den Port EINMAL an (beim Programmstart) d.h. Du mußt einmal in den sauren Apfel beißen. Den Pointer speicherst Du dann in einer Variable und nutzt diese dann bei allen Message-Sende-Aufrufen OHNE Forbid/Permit (und natürlich auch OHNE FindPort).

Bei dieser Variante tritt genau das von mir oben beschriebene Phänomen auf. Tritt ein Reschedule auf, während ein Client eine Nachricht an meinen Server sendet und der Server (der jetzt der neu gestartete Task ist) seinen Port schließt, dann fällt der Client in einen Deadlock!
Deshalb möchte ich hier gerne eine Semaphore verwenden, da damit nur der Server oder seine Clients beim Message-Senden blockiert werden, nicht aber das ganze Multitasking! Die Frage ist nur wie??

mfg
Geri

--
Southtyrolean Amiga user since 1989!

[ - Antworten - Zitieren - Direktlink - ]

12.08.2003, 14:21 Uhr

Inferno
Posts: 157
Nutzer
Hi Geri,

Du mußt nicht unbedingt auf den Reply warten. Du kannst eine Message auch "einfach so" losschicken. Allerdings solltest Du überprüfen, ob das Verschicken auch geklappt hat. Die Funktion sollte Dir entweder 'nen Fehlerwert zurückgeben, oder Du kannst ihn abfragen (bin gerade im Büro, da kann ich nicht in den Docs nachsehen :) )

Wenn Du die Anwort brauchst, kannst Du ja genau dann die Wait-Funktion aufrufen, wenn die SendMessage - funktion keinen Fehler zurückgeliefert hat.

Aber mal generell 'ne andere Idee: Wenn Du sowieso eine Client-Server-Anwendung schreibst, dann wäre es vielleicht besser, das ganze per Sockets zu machen. Dadurch ist der Server dann auch (im Netzwerk - sofern vorhanden) von mehreren Rechner aus verfügbar. Außerdem mußt Du Dich nicht mehr um Synchronisation o.ä. kümmern. Wenn der Server da ist, funktionierts, andernfalls bekommst Du einen Fehlerwert zurück. Du kannst senden und antworten so wie es Dir/Deinem Programm gefällt ...

Ciao,

Inf.

[ - Antworten - Zitieren - Direktlink - ]

12.08.2003, 15:34 Uhr

Geri
Posts: 138
Nutzer
Hi Inferno!

Zitat:
(bin gerade im Büro, da kann ich nicht in den Docs nachsehen)
Willkommen im Club. Da müssen wir wohl noch etwas ausharren!!

Ach so, ich dachte immer die Messages müßten zurückgesandt werden! Okay, ich werde das nochmals in den Autodocs und den Reference Manuals nachlesen.

Zitat:
Aber mal generell 'ne andere Idee: Wenn Du sowieso eine Client-Server-Anwendung schreibst, dann wäre es vielleicht besser, das ganze per Sockets zu machen. Dadurch ist der Server dann auch (im Netzwerk - sofern vorhanden) von mehreren Rechner aus verfügbar.

Naja, so weit wollte ich es eigentlich nicht treiben, da ein TCP/IP Stack schon etwas CPU-lastig ist. Das mit dem Client-Server System war so wie bei einem Client-Server OS gedacht, d.h. der Microkernel (Exec) übernimmt das IPC und der Server und die Clients kommunizieren nur über simple Messages.
Man könnte den Server auch als Library oder Device implementieren, allerdings hat man dann keine so große Flexibilität (denk ich mal), wenn sich z.B. das API ändern sollte!
Später kann man ja immer noch einen Client schreiben, der als Server für Nachrichten übers Netz dient.

Geri

--
Southtyrolean Amiga user since 1989!

[ - Antworten - Zitieren - Direktlink - ]

12.08.2003, 17:28 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Geri:
Eine eigene Semaphore die von einem Client "besetzt" werden kann ist eine Lösung. Dabei geht jedoch die Kompatibilität zu den alten Client-Applikationen verloren.
Allerdings würde ich den öffentlichen Port nur mehr für dia alten Applikationen benötigen und die neuen könnten sich über die Semaphore mit dem Server synchronisieren. Sehe ich das richtig?

Irgendwie scheint Dir die Funktionsweise von Semaphoren nicht ganz klar zu sein. Die zu synchronisierenden Prozesse müssen ein und dieselbe Semaphore benutzen. Und wie willst Du die Semaphore von Prozess a nach Prozess b übergeben, wenn zu diesem Zeitpunkt keine saubere Kommunikation sichergestellt ist?

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

12.08.2003, 17:49 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Geri:
Bei dieser Variante tritt genau das von mir oben beschriebene Phänomen auf. Tritt ein Reschedule auf, während ein Client eine Nachricht an meinen Server sendet und der Server (der jetzt der neu gestartete Task ist) seinen Port schließt, dann fällt der Client in einen Deadlock!
Deshalb möchte ich hier gerne eine Semaphore verwenden, da damit nur der Server oder seine Clients beim Message-Senden blockiert werden, nicht aber das ganze Multitasking! Die Frage ist nur wie??

Viel zu umständlich. Wenn Du eine Message-Kommunikation hast, dann benutz sie doch einfach. Lass den Server vor dem Beenden eine Nachricht an alle Clients schicken, die den bevorstehenden Abschied mitteilt und beende ihn erst, wenn alle Clients geantwortet haben.
Alle zwischenzeitlich noch von Clients verschickte Nachrichten erreichen den Server vor der Bestätigungsantwort und können noch korrekt abgearbeitet werden.

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

12.08.2003, 17:58 Uhr

Geri
Posts: 138
Nutzer
Zitat:
Original von Holger:
...

Irgendwie scheint Dir die Funktionsweise von Semaphoren nicht ganz klar zu sein. Die zu synchronisierenden Prozesse müssen ein und dieselbe Semaphore benutzen. Und wie willst Du die Semaphore von Prozess a nach Prozess b übergeben, wenn zu diesem Zeitpunkt keine saubere Kommunikation sichergestellt ist?


Gute Frage!! Da läuft was falsch bei mir... ?(

Ich hatte das so verstanden: Der Server erzeugt eine öffentliche Mutex (ich glaube so sollte es richtig sein. Semaphore ist der völlig falsche Ausdruck!), die zum Senden von Messages benutzt wird. Will ein Client eine Message senden, so versucht er die Mutex zu erwerben. Kann er dies nicht, so wird er blockiert. Erwirbt er die Mutex, so sendet er die Nachricht und gibt sie dann wieder frei. Das Multitasking wird nicht abgeschalten, sondern es werden nur die Tasks blockiert die Nachrichten an den Server senden wollen. Ein Client muß vorher nur nach der Mutex mit dem entsprechenden Namen suchen. Jetzt stellt sich mir nur die Frage ob es so etwas wie Mutex im AmigaOS gibt?

Geri


--
Southtyrolean Amiga user since 1989!

[ - Antworten - Zitieren - Direktlink - ]

14.08.2003, 22:32 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Geri:
Ich hatte das so verstanden: Der Server erzeugt eine öffentliche Mutex (ich glaube so sollte es richtig sein. Semaphore ist der völlig falsche Ausdruck!), die zum Senden von Messages benutzt wird.

Also, Du kannst eine Semaphore öffentlich zugänglich machen. Nach dem Anlegen rufst Du AddSemaphore() auf. Dann kann der Client FindSemaphore() aufrufen, bekommt ein Handle und kann dann ObtainSemaphore() locken. Das sieht nicht nur genauso aus, wie bei öffentlichen Ports, es weist auch genau das gleiche Problem auf: Wer sagt Dir, daß die von FindSemaphore zurückgegebene Semaphore überhaupt noch existiert, wenn Du ObtainSemaphore() aufrufen willst?
Somit lautet die Schlußfolgerung: wenn das Hantieren mit Semaphoren in keinster Weise Dein Problem lösen kann, kannst Du Dir das auch sparen.
Bleib einfach beim normalen Message-Handling. Wie gesagt, das Beenden kannst Du durch eine entsprechende Shutdown-Message sauber lösen. Das Anmelden kannst Du derzeit nur dadurch lösen, daß Du entweder eben mit Forbid()+FindPort()+PutMsg()+Permit() arbeitest, oder auf einen Mechanismus zurückgreifst, der das synchronisierte Anmelden mitbringt, z.B. eine Library programmieren. Da löst exec das Problem für Dich.

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]


-1- [ - Beitrag schreiben - ]


amiga-news.de Forum > Programmierung > Messages senden ohne Forbid(); [ - Suche - Neue Beiträge - Registrieren - Login - ]


.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
.