Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Konzept gesucht - Interprocess communication (https://www.delphipraxis.net/99204-konzept-gesucht-interprocess-communication.html)

Zacherl 8. Sep 2007 14:56


Konzept gesucht - Interprocess communication
 
Hey,

ich möchte folgendes realisieren:

1 Prozess ist aktiv, welcher einen 2. startet. Dieser 2. Prozess soll prüfen ob Prozess 1 noch läuft und diesem gegebenenfalls neu starten.

Dabei möchte ich Memory Mapped Files verwenden. In Prozess 1 läuft ein Thread, welcher alle 5 Sekunden GetTickCount in das MMF schreibt. Prozess 2 guckt jede 10 Sekunden ob der ausgelesene Wert < GetTickCount + 10 ist. Wenn nicht wird Prozess 1 neu gestartet.

Wie findet ihr dieses Konzept? Könnte man es über Named Pipes evtl. einfacher lösen?

Gruß Florian

Reinhard Kern 8. Sep 2007 15:03

Re: Konzept gesucht - Interprocess communication
 
Zitat:

Zitat von Zacherl
Hey,

ich möchte folgendes realisieren:

1 Prozess ist aktiv, welcher einen 2. startet. Dieser 2. Prozess soll prüfen ob Prozess 1 noch läuft und diesem gegebenenfalls neu starten.

Dabei möchte ich Memory Mapped Files verwenden. In Prozess 1 läuft ein Thread, welcher alle 5 Sekunden GetTickCount in das MMF schreibt. Prozess 2 guckt jede 10 Sekunden ob der ausgelesene Wert < GetTickCount + 10 ist. Wenn nicht wird Prozess 1 neu gestartet.

Wie findet ihr dieses Konzept? Könnte man es über Named Pipes evtl. einfacher lösen?

Gruß Florian

Hallo,

wozu GetTickCount austauschen? Es genügt doch, wenn P1 alle 5 sec eine Botschaft sendet "bin noch da" und P2 prüft das (mit einem Timer) nach dem Prinzip Watchdog - das geht sogar mit einer Windowsmessage. Wenn P2 mit einer Botschaft antwortet, können sie sich gegenseitig überwachen.

Gruss Reinhard

Zacherl 8. Sep 2007 15:13

Re: Konzept gesucht - Interprocess communication
 
Ich weiß nicht genau wie das ist bei MMFs. Der reingeschriebene Wert bleibt doch im File stehen, auch wenn ich ihn ausgelesen habe, oder nicht? Weil wenn ja, dann würde der Wert auch drin stehen bleiben, wenn P1 längst terminiert wurde.

himitsu 18. Jan 2008 22:54

Re: Konzept gesucht - Interprocess communication
 
(ich weiß, is schon ein bissl alt, aber Überschrift und Thema passen zu meinem Problem, also wozu einen neuen Thread aufmachen :roll: )

MMFs muß man ja nicht mit einer Datei verknüpfen und dann liegt nur eine virtuelle Datei im Arbeitsspeicher.

Wenn dann beide Prozesse beendet sind, dann wird der Speicher (also die Datei) freigegeben.


Aber für dein Problem ist es wohl wirklich am einfachsten sich Windowsnachrichten hin und eventuell zurückzuschicken.

A schickt alle 10 Sekunden eine Nachricht an B

und mißt die Zeit zur letzten empfangenen Nachricht ... z.B. 20-30 Sekunden keine Meldung von A, dann wird A neu gestartet.

> größere Zeit beim Prüfen, da Messages nicht unbedingt sofort ankommen und es mal mehr als 10 Sekunden dauern kann.






So, nun zu mir...

mein Programm hat schon eine IPC via WMs, aber nun bräuchteich noch eine bidirektionale Übertragung größerer Datenblöcke.

WM_COPYDATA geht ja nur zum Versenden und empfangen wirde bei der Implementierung wohl vollkommen ignoriert :?

also was wie Folgendes geht halt nicht.
Delphi-Quellcode:
X:Zeiger := ...;
X.MaxLen := 123456;
SendMessage(Wnd, WM_COPYDATA_RECIVE, @X, 0);

{ oder }

X := SendMessage(Wnd, WM_COPYDATA_RECIVE, 0, 0);
//X = sowas wie COPYDATASTRUCT
Eine nachricht al Anfrage zu senden und dann auf eine antwort z.B. per WM_COPYDATA zu warten ist auch nicht so optimal (Nachrichtenabarbeitungsreinfolge und Threadsicherheit würden da etwas leiden und müßten zusätzlich nochmals geprüft werden)

hab mich auch in letzter Zeit nach Com, ActiveX, Interfaces umgesehn, aber so richtig hab da noch icht durchgesehn :oops:

So wie Named-Pipes und Mail-Slots hat auch wieder andere Nachteile.

nunja und MMFs scheinen auch manchmal Probleme zu machen (z.B. kein Zugriff unter Vista u.a.)
Aber dennoch wollt ich's damit mal versuchen...

mein Code würde dann in etwa so aussehn:
- kleiner Testcode ohne (richtige) Fehlerbehandlung und Co.
- und noch nicht auf verschiedene Prozesse verteilt
das "Begin (* ... *)" bis "End;" stellt sozusagen jeweils den Messagehandler des Fremdprozesses dar
Delphi-Quellcode:
Const AllocSize = 64 * 1024; {diese größe wird dann auch noch dynamisch :wall: }

Var SourceMap, DestMap, H, S, R: THandle;
  Ps, Pd: Pointer{PAnsiChar};

Begin
  Try
    {MMF erstellen}
    SourceMap := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, AllocSize, nil);
    If SourceMap = INVALID_HANDLE_VALUE Then Exit;

    {was in die MMF reinschreiben ... zum Senden, falls nötig}
    Ps := MapViewOfFile(SourceMap, FILE_MAP_WRITE, 0, 0, 0);
    If Ps = nil Then Exit;
    // Copy(Ps, irgendwas)
    UnmapViewOfFile(Ps);

    {Handle der MMF für anderen Prozeß erstellen}
    {}If not DuplicateHandle(GetCurrentProcess, GetCurrentProcess, GetCurrentProcess, @H,
    {}  PROCESS_DUP_HANDLE, False, 0) Then Exit;
    //H := OpenProcess(PROCESS_DUP_HANDLE, False, GetCurrentProcessId);
    //If H = 0 Then Exit;
    S := SourceMap;
    Begin (* R := SendMessage(Wnd, WM_DUPLICATE_HANDLE, H, S); *)
      If not DuplicateHandle(H, S, GetCurrentProcess, @R,
        0, False, DUPLICATE_SAME_ACCESS) Then Exit;
    End;
    DestMap := R;

    {Nachricht senden}
    {und drüben die MMF auslesen/bearbeiten}
    H := DestMap;
    Begin (* R := SendMessage(Wnd, WM_MACHWAS, wmDiesUndDas, H); *)
      Pd := MapViewOfFile(H, FILE_MAP_READ{FILE_MAP_WRITE}, 0, 0, 0);
      If Pd = nil Then Exit;
      // Copy(Pd), oder so
      UnmapViewOfFile(Pd);
      CloseHandle(DestMap);
    End;

    {MMF auslesen ... zum Empfangen, falls nötig}
    Ps := MapViewOfFile(SourceMap, FILE_MAP_READ, 0, 0, 0);
    // Copy(irgendwas, Ps)
    UnmapViewOfFile(Ps);

    {MMF freigeben}
    CloseHandle(SourceMap);
  Finally
    Application.MessageBox(PChar(SysErrorMessage(GetLastError)), PChar(Caption));
  End;
End;
müßte doch so in etwa funktionieren ... denk ich mal.



nun ist mir dabei aber was aufgefallen ...

weil ich keine Names-MMFs verwenden kann (ein/zwei Günde nachfolgend) übergebe ich nun statt einen "Pointers auf die Daten" den Handle zur MMF.

... und da ich ja zur Handleübergabe das Prozeßhandle benötige, könnte ich doch eigentlich gleich statt PROCESS_DUP_HANDLE einfach PROCESS_VM_OPERATION+PROCESS_VM_READ+PROCESS_VM_WR ITE verwenden
und dann direkt via VirtualAllocEx+Read/WriteProcessMemory zugreifen? :gruebel:

unter Anderem könnte dann die angefragte Anwendung dann selber die Größe des Rückgabepuffers festlegen und ich müßte nicht vorher über eine zusätzliche Abfrage rausbekommen wieviel Speicher die MMF mindestens haben muß.


Gründe + grobe Programmstruktur:
- es gibt einen "Clienten", welcher von einem/mehreren "Servern" gesteuert wird, wobei die Server nicht wissen (müssen) das/ob es andere gibt.
- die Server können (müssen aber nicht) sich per WM beim Clienten anmelden und dort ein Handle und eine WM-ID hinterlegen, worüber sie eine Mitteilung bekommen, sobald sich was am Datenbestand durch irgendwen verändert hat.
- der Client steht immer auf Empfang und jeder Server kann ohne Voranmeldung senden
- es besteht aber die Möglichkeit zugriffe die Zur änderung der Daten im Clienten führen zu sperren (kann ein Server explizit beantragen, falls nötig)
- es können aber auch mehrere Clienten existieren (zwar sehr unwahrscheinlich, aber dennoch hab ich diese Möglichkeit offengelassen)

Dank der WM (SendMessage und Co) ist das ganze aber dennoch Threadsave, da schließlich immer nur eine WM zum selben Zeitpunkt verarbeitet wird,
was bei bidirektionaler Kommunikation per WM wiederum verlorengehen kann (drum kein WM_COPYDATA)

> Server sendet neue Daten oder fragt welche ab
> Client gibt bei Änderung über PostMessage (nur Integer und Co.) an registrierte Sever eine Meldung aus
= also keine gegenseitige Blockierung möglich


Mehrere Clienten/Server, darum keine Named-Pipes und Named-MMFs ... wie sollte ich da denn die Namen versenden, da ich ja grad zum Versenden/Empfangen von Namen und Dergleichen dieses benötige ...
wär ja so, als ließe ich das Huhn sein eigenes Ei legen lassen :stupid:



Was meint ihr?
- die MMFs weiter ausbauen (hab's erstmal aufgehört und andere Möglichkeiten betrachtet, aber es ist schon was vorhanden)
- Direktzugriff (weniger Code = fehlerunanfälliger und dann auch noch ein einfacheres Speichermanagement)
oder habt ihr bessere Ideen?
- was ganz anderes (wenn ich Pech hab, darf ich da auch noch die gesamte Nachrichtenbehandlung und Programmstruktur ändern)


Ach ja, sollte die Kommunikation nur innerhalb des PCs (kein Netzwerk) und der selben Benutzerebene ablaufen ... jedenfalls fällt mir kein wirklcher Grund ein, warum beides/alles weiter auseinander sein sollte
und Vor-Win2000pro unterstütz ich auch nicht mehr explizit (also wenn es da nicht läuft ... egal :angel2: )




Es gibt halt unzählige Möglichkeiten mit massig Vorteilen, aber wenn man die dann versucht auf ein bestimmtes Problem anzuwenden, dann hat alles irgendwie nur noch Nachteile :freak:


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz