kommunikation zwischen Scripten

  • Moin,

    ich habe 4 Scripte die untereinander via Console kommunizieren.
    Script A startet Script B, Script B startet Script C und Script D. Script B übergibt Script D den Handle zu Script A.

    So, jetzt habe ich das Problem, dass Script D nichts in die Console von Script A schreiben kann. Ist das normale? Von B nach C oder von B nach D funktioniert das problemlos.

    Gibt es dafür einen Grund? Ich könnte mir irgend wie denken, dass nur Parents was an die Children schicken können und von dort auch alles lesen aber nicht andersrum.
    Wenn ich recht habe, gibt es eine Alternative, dass ich von Script D nach Script A etwas verschicken kann?

  • Das nennt sich IPC (Inter Process Communication) und wird im engl. Forum mit mehreren Lösungen diskutiert.
    Mein Favorit ist MailSlot von trancexx.

  • Das nennt sich IPC (Inter Process Communication) und wird im engl. Forum mit mehreren Lösungen diskutiert.
    Mein Favorit ist MailSlot von trancexx.


    Das sieht sehr vielversprechend aus. Ich vermute du hast schon Erfahrung damit.
    Was ist, wenn ich da hunderte von Nachrichten hin und her schicke innerhalb einer sehr kurzen Zeit? z.B. 100 Nachrichten in 3 Sekunden?

    /Edit:
    Ich habe gerade gesehen, dass ich eine "Adresse" immer nur von einem Script abfragen darf.

    [autoit]

    Global $hMailSlot = _MailSlotCreate($sMailSlotName)
    If @error Then
    MsgBox(48 + 262144, "MailSlot", "Failed to create new account!" & @CRLF & "Probably one using that 'address' already exists.")
    Exit
    EndIf

    [/autoit]


    Jetzt zurück zu meinem Beispiel oben. Ich habe Script C aber 3x (machen alle das selbe nur ein verteilten Aufgaben). Ist es irgend wie möglich mehrere Verbindungen zu einer Adresse aufzubauen?

    Einmal editiert, zuletzt von Freaky (14. März 2015 um 15:00)

  • Der Mailslot-Name muss eindeutig sein. Aber wenn z.B. Skript C drei Mal Skript D startet, dann kannst Du ja drei Mailslots mit der jeweiligen Prozess-ID erstellen.

  • Interprozesskommunikation mit gleichen Speicherzugriff funktioniert am besten mit einer DLL. Da können sich beliebig viele Prozesse einklinken und dann auf ein und denselben Speicherbereich zugreifen. Im Anhang findest du ein Beispiel mit den nötigen flatassembler Code. Solltest du einen entsprechenden Compiler haben, kannst du den Speicherbereich selber erhöhen, ich habe dir das mal mit 256kb kompiliert. Dazu auch ein Beispielskript, einfacher Zugriff über DllStructs... :)

  • Hi,

    B startet C 3x und D 1x

    Ich möchte aber sowas wie, dass alle Cs auf die selbe Adresse zugreifen.


    Beim von Homer J.S. verlinkten Post greifen ALLE Prozesse SIMULTAN auf den geteilten Speicher zu, das ist der Sinn der Sache!
    JEDES der gestarteten Scripte initialisiert den Speicher über die DLL, alle nachfolgend gestarteten Scripte greifen auf diesen Speicherbereich zu.

    Wenn man mag, kann man einzelne Speicherbereiche einfach über die Startadresse und das Offset selektiv benutzen.
    Angenommen, man hat 8 Programme, die alle auf den gleichen Speicher zugreifen, dann ist das "normal". Gebraucht werden 10 KBytes, reserviert wird aber 1Mbyte.
    Gleichzeitig benötigt man bei Programm5 bis Programm8 noch gemeinsamen Speicher, dann richtet man eben ab Offset 10 bis 20KB weiteren geteilten Speicher ein usw usf.
    Habe das testweise auf Win Server8 mit 20 gleichzeitig laufenden, einzelnen Prozessen getestet, das funktioniert einwandfrei. Was auch niemanden wundern sollte, denn genau DAS ist der Grund, warum es überhaupt DLL´s gibt....

  • Mal ne Frage weil ich die SharedMemory.dll nicht kenne.
    Wie sie sieht es dort mit Thread-Sicherheit aus? - Stichwort "race conditions" oder "lost update"?
    Wie wird das dort gewährleistet?

  • Sicherheit? Das ich nicht lache. Rein theoretisch können sich auch fremde Prozesse einklinken und lesen was das Zeug hält. Es liegt am Programm dafür zu sorgen dass ein wechselnder Schreibe und Lesezugriff entsteht, da müssen gewisse Mechanismen eben selber programmiert werden. Die DLL ist dafür nicht ausgelegt, aber man könnte dies bei Gelegenheit tatsächlich noch implantieren.

    Dafür hat man aber völlige Kontrolle, man bekommt den Speicherplatz und kann ihn nutzen wie man will. Ein direkter Zugriff ohne Umwege, die schnellste Möglichkeit der Interprozesskommunikation. Dafür fehlt aber sämtliche Sicherheit. ^^

    Wenn ich (oder Andy [was mir lieber wäre xD]) die Lust oder Zeit finden, dann könnte man noch die nötigen Sicherheitsvorkehrungen treffen. Wäre aber halt Arbeit. :P

  • Mal ne Frage weil ich die SharedMemory.dll nicht kenne.

    Thread dazu: Kommunikation Skripte untereinander

    Im Prinzip wird nichts weiter gemacht, als per FASM eine DLL mit genau einer Funktionen zu erstellen, die lediglich den Pointer auf einen per sharable/writable gekennzeichneten Speicherbereich zurückgibt.
    Ich bin mir nicht ganz sicher, ob dieses "Feature" überhaupt im Sinne des Erfinders ist, jedenfalls habe ich in einigen Foren in Threads zu diesem Thema festgestellt, dass irgendwann ein MS-Spezialist auftaucht, der einfach festlegt, dass so etwas garnicht funktioniert. Soviel dazu....

    Threadsicherheit hatte ich ehrlich gesagt nie auf dem Schirm :D
    Ich vermute aber, da es sich um eine einfache DLL handelt, dass das Betriebssystem bei Schreibzugriffen genau wie bei "gleichzeitigen" Aufrufen von Funktionen aus DLL´s handelt.
    Bei Aufruf einer DLL-Funktion aus mehreren Threads wird jeweils ein lokaler Instructioncache angelegt und per Scheduler (vom Betriebssystem) abgearbeitet. Das ist simples Threadmanagement per Zeitscheiben.
    Beim Zugriff auf "sharable" Speicher stelle ich mir ähnliches vor, ansonsten würde es permanent exceptions hageln.
    Wenn also mehrere Threads "gleichzeitig" auf den von der DLL bereitgestellten Speicher zugreifen, managed das Betriebssystem die Zugriffe, ähnlich wie beim gleichzeitigen Zugriff auf Dateien.

    Wie in diesem Post gezeigt, Kommunikation Skripte untereinander , ist "gleichzeitiges" Schreiben und Lesen völlig problemlos. Jedenfalls in dieser "einfachen" Form.

    Aber zu deinen Fragen^^ :
    "lost updates" sind ein Programm(ier(er))-Fehler. Wenn dieser Fall auftritt, hat irgendwer im VORFELD gepennt! Wenn bspw. 10 User "gleichzeitig" einen Wert in eine Datenbank schreiben wollen und dann keine Rückfrage an ALLE Beteiligten kommt, welcher dieser Werte denn nun "aktuell" ist, liegt imho der Fehler keinesfalls bei der Funktion "_DatenSchreiben()".
    "Race conditions" sind imho per definitionem garnicht zu vermeiden! Das bekommt man nur dann geregelt, wenn (wiederum im Vorfeld! ) genau festgelegt wird, in welcher Reihenfolge Schreib/Lesezugriffe abgewickelt werden, also per vorher definierter, zeitlich bestimmter Prioritätenliste.
    Stell dir vor, bei einem Leichtathletik-Wettkampf würde beim 100m-Lauf jeder Läufer einfach beim Startschuss losrennen und dann so schnell wie es ihm möglich ist, ins Ziel renenn! Wo kämen wir denn da hin! Chaos! Keinerlei Zuverlässigkeit in der Reihenfolge des Ziel-Einlaufs! Der schnellte wäre zuerst im Ziel.
    Ein "richtiger" Programmierer würde in diesem Fall VORHER festlegen, in welcher Reihenfolge die Läufer im Ziel einzulaufen haben. DAS ist aber garnicht beabsichtigt....oder doch....oder doch nicht ?! :rolleyes:

  • O.k. danke für die Info.
    Dann sollte man vielleicht nochmal explizit darauf hinweisen.
    Nicht das noch jemand seine Programme darauf aufbaut und wundert warum der Kunde sich darüber beschwert, dass er jedesmal ein anderes Ergebnis bekommt...

    "lost updates" sind ein Programm(ier(er))-Fehler.

    Nein sind sie per se nicht.
    Exakt darum drehte sich ja meine Frage. Man muss sie beachten und mit geeigneten Mitteln verhindern. Aber wenn man (wie hier) keine Werkzeuge zur Hand hat sie zu verhindern kann der Programmierer auch nicht viel machen.

    "Race conditions" sind imho per definitionem garnicht zu vermeiden!

    Klar lassen sie sich mit z.B. mit Mutex's oder Locks verhindern.

  • Man muss sie beachten und mit geeigneten Mitteln verhindern.

    Wahrscheinlich habe ich mich (wie so oft) unklar ausgedrückt...
    Wenn du schreibst "MAN muss..und mit geeigneten Mitteln..." wer ist dann mit MAN gemeint? Natürlich ist es so, dass ausschliesslich der Programmierer für den Kram den er verzapft, verantwortlich zu machen ist.
    Genauso wie übrigens

    Klar lassen sie sich mit z.B. mit Mutex's oder Locks verhindern.

    der Programmierer dafür sorgen muss!

    Wer auch sonst?

    Wenn per Lock/Mutex im VORFELD (!) gearbeitet wird, entstehen die angesprochenen "Probleme" erst garnicht! Im Umkehrschluss heisst das, dass bei Race Conditions (der "Zustand" existiert ! ) das Kind bereits in den Brunnen gefallen ist....die Existenz von Race Conditions impliziert schon den "nicht vermiedenen Fehler".

  • Klar - in den Brunnen gefallen ist es schon.
    Wie sperrt man aber, auf Basis dieser Dll den Brunnen ab?
    Eigene Mutex' zu implementieren wird alleine deshalb schon witzig weil schon race-conditions auf die Mutex stattfinden können.
    Einen Programmierer einen shared memory zu Verfügung zu stellen ist eine Sache.
    Ihm sichere Schnittstellen hierfür anzubieten ist nochmal ne andere.

    Diese SharedMemory.dll mag ja ganz witzig sein aber ich halte es für bedenklich das als die Lösung für Interprozesskommunikation anzubieten ohne die Nutzer (und wahrscheinlich auch ne Menge Neueinsteiger im Bereich paralleler Programmierung) für die damit verbundenen "Gefahren" zu sensibilisieren.

    Edit: Die Windows-API bietet hierfür entsprechende Funktionen.
    Man muss sie nur nutzen.
    Das simpelste Beispiel, aber das welches man wahrscheinlich immer beim Multi-Processing benötigt wäre die threadsichere Implementierung eines Prozess-Zählers.
    Hierfür kann man z.B. die Funktionen InterlockedIncrement/InterlockedDecrement verwenden.
    Damit ist sichergestellt, dass der Zähler nicht aufgrund von race-conditions oder lost updates falsche Werte erhält:

    Threadsichere Counter für die sharedmemory.dll
    [autoit]

    #AutoIt3Wrapper_UseX64=n
    #AutoIt3Wrapper_Change2CUI=y

    [/autoit] [autoit][/autoit] [autoit]

    $hDLL = DllOpen('SharedMemory.dll')
    $ptr = DllCall($hDLL, 'ptr', 'GetPtr')[0]
    $size = DllCall($hDLL, 'dword', 'GetSize')[0]

    [/autoit] [autoit][/autoit] [autoit]

    ; Die Speicherstelle an der die Anzahl Threads steht (hier die ersten 4 Bytes des shared memory)
    ; Da ein neuer Prozess erstellt wurde, wird dieser Wert um eins erhöht
    $d_ThreadID = DllCall("Kernel32.dll", "Long", "InterlockedIncrement", "ptr", $ptr)[0]

    [/autoit] [autoit][/autoit] [autoit]

    $iT = TimerInit()
    Do
    $d_ThreadN = DllStructGetData(DllStructCreate("LONG", $ptr), 1)
    ConsoleWrite(StringFormat("Ich bin Prozess %d von %d\n", $d_ThreadID, $d_ThreadN))
    Sleep(1000)
    Until TimerDiff($iT) > 15000

    [/autoit] [autoit][/autoit] [autoit]

    ; Da der Prozess beendet wird, den Threadzähler wieder um eins verringern:
    DllCall("Kernel32.dll", "Long", "InterlockedDecrement", "ptr", $ptr)

    [/autoit]


    Das Skript kompilieren und mehrmals hintereinander starten - dann sollte der Sinn klar werden.

    2 Mal editiert, zuletzt von AspirinJunkie (15. März 2015 um 20:13)

  • Ja, ich gebe dir voll und ganz recht!
    Wer keine Ahnung hat, der soll die Finger davon lassen!
    Das gilt übrigens nicht nur für den Bereich "Paralleles Programmieren".
    Nirgends steht geschrieben, dass diese Methode die einzig wahre ist. Allerdings halte ich es für eine sehr simple und zuverlässige Methode, um mit einer Handvoll Zeilen Code egal aus welcher Programmiersprache auch immer (nagut, Zugriff auf eine DLL sollte sie bieten ^^ ) einfache Interprozesskommunikation zu verwirklichen.
    Wenn ich mir allerdings die gängigen Fragen hier im Forum zum Thema "gleichzeitig Funktionen laufen lassen" bzw. "AutoIt und Multithreading" anschaue, habe ich keine Angst, dass so jemand auch nur ansatzweise etwas über die von dir gemeinten "Gefahren" hören möchte...bzw. diese "Gefahren" auch nur im entferntesten versteht.

    Gerade im Gegenteil finde ich es eher interessant, sich mit wirklich rudimentären Mitteln beschäftigen zu können um dann anhand bspw. dieser Konversation einen etwas tieferen Einblick in das Thema zu erhalten.
    Der Weg ist das Ziel!
    Oder wie der Franzose sagt, "learning by doing"!

    //EDIT zum Script
    Genau so meinte ich das mit der "Entwicklung". Sehr nice :thumbup:

  • Gerade im Gegenteil finde ich es eher interessant, sich mit wirklich rudimentären Mitteln beschäftigen zu können um dann anhand bspw. dieser Konversation einen etwas tieferen Einblick in das Thema zu erhalten.
    Der Weg ist das Ziel!

    Wahrscheinlich hast du Recht.
    Es ist wohl wie bei der Kindererziehung: Gib ihnen wenigstens die Chance eigene Fehler zu machen.

    Diese Methode hier ist dafür schon fast ein kleines Paradies und wird dem, welcher damit spielt, wohl mehr vermitteln als die meisten Tutorials es wohl jemals könnten. :thumbup: