Zum Hauptinhalt springen

Das OpenVOS-Betriebssystem bietet eine hochentwickelte Anwendungsprogrammierschnittstelle (API), die die Programmierung des Systems insgesamt vereinfacht. Manchmal wird es jedoch zu einfach – denn ein einfacher Unterprogrammaufruf an eine s$-Routine kann eine Menge Komplexität verbergen.

Dies ist der erste Beitrag einer unregelmäßigen Reihe, die Sie auf solche Fallstricke aufmerksam machen soll, damit Sie diese bei Ihren Anwendungsdesigns vermeiden können.

Die Nachteile von Nachrichten mit 25 Zeilen

Die Möglichkeit, eine Nachricht in die25. Zeile (oder die unterste Zeile) eines Terminals zu schreiben, ermöglicht es einem Benutzer (oder einem laufenden Programm), andere Benutzer über ungewöhnliche Zustände zu benachrichtigen. Die Befehlszeilenschnittstelle ist der Befehl send_message. Der Befehl und die Benutzerprogramme rufen letztendlich die API-Subroutine s$send_message auf.    Die Argumente für diesen Aufruf sind der Benutzername des Empfängers, der Name des Zielmoduls, in dem dieser Benutzer möglicherweise angemeldet ist, der Benachrichtigungstext und einige Flags zur Änderung von Aspekten des Vorgangs. Privilegierte Aufrufer dürfen den Namen des Absenders angeben, andernfalls wird standardmäßig der Benutzername des sendenden Prozesses verwendet.

Bisher scheint alles klar zu sein. Da für den Vorgang Zugriff auf das Terminal eines anderen Benutzers erforderlich ist, sendet der Kernel die Anfrage an eine Serverwarteschlange für den TheOverseer-Prozess auf dem Zielmodul. Normalerweise wartet der sendende Prozess dann auf den Status der Nachrichtenübermittlung, kann aber auch entscheiden, nicht auf diese Antwort zu warten.

Der Overseer-Prozess für jedes Modul verfolgt alle Anmeldevorgänge und die von diesen Prozessen verwendeten Endgeräte.   Wenn er eine Anfrage zum Senden einer Nachricht erhält, durchsucht er seine Liste von Prozessen und Geräten und fügt für jeden Prozess user_name, der mit dem Argument receiver_name übereinstimmt, einen Port an das Endgerät des Prozesses an, öffnet den Port, schreibt die Nachricht in die Benachrichtigungszeile, schließt den Port und trennt den Port. Wenn mehrere Prozesse mit dem Argument receiver_name übereinstimmen, wird dieser Zyklus aus Anfügen/Öffnen/Schreiben/Schließen/Trennen für jeden einzelnen wiederholt.

Okay – das ist etwas komplizierter, als wir zunächst angenommen hatten. Bei näherer Betrachtung stellen wir fest, dass jedes beliebige Modul im System Anmeldeprozesse hosten kann, bei denen das eigentliche Terminal ein Gerät auf einem anderen System/Modul ist, das Open StrataLink (OSL) verwendet hat, um sich über das Netzwerk anzumelden (mit dem Befehl „login –module“).   Nun müssen die scheinbar einfachen Vorgänge „Anfügen/Öffnen/Schreiben/Schließen/Trennen“ auf diesem Terminal OSL-Prozesse und Netzwerk-Remote-Prozeduraufrufe an das Remote-Modul beinhalten und sind damit wesentlich aufwendiger als die Verarbeitung auf dem Modul.

Die Auswirkungen werden verstärkt, wenn der Empfänger „user_name“ als Sternname angegeben wird, der mit mehreren oder allen angemeldeten Benutzern übereinstimmen könnte. Und sie werden noch verstärkt, wenn das Zielmodul ebenfalls als Sternname angegeben wird. Der schlimmste Fall wäre das Senden der Nachricht an den Benutzer „*.*“ (alle Benutzer, alle Gruppen) auf dem Modul „*“ (alle Module des aktuellen Systems).

Umsetzung

s$expand_module_starname(target_module) =>  module_list;

foreach module_name in module_list
   send_overseer_request(module_name, send_message_request_data)
   The message is sent via a server queue and OSL to TheOverseer process
   on that module.

   TheOverseer  process on each receiving module then does:
   foreach terminal_process in TheOverseer’s list of
      login processes and sub-processes;

      if (terminal_process user_name matches receiver star name)
         if (messages_queued_for_device < 5)
            queue it for the login device
         else
            reject the request (e$too_many_terminal_messages)
   Verwenden Sie gleichzeitig bis zu 10 Ports, um alle in der Warteschlange stehenden Nachrichten an die Terminals zu senden.
   Für jede Nachricht für jedes Terminal
   Port anhängen
   Port öffnen
   s$control(…WRITE_SYSTEM_MESSAGE…)
   Port schließen
   Port trennen

Diese Verarbeitung erfolgt im no_wait_mode für jedes Terminal, sodass
Verzögerungen (z. B. durch E/A-Anforderungen über das Netzwerk) nur die
Nachrichtenverarbeitung für dieses Terminal beeinträchtigen.   


Wenn eine Nachricht nicht innerhalb von 300 Sekunden zugestellt werden kann, wird sie gelöscht.

Wenn eine Anwendung diesen Mechanismus zur Fehlermeldung nutzt und eine Flut von Fehlern auftritt, kann die Anwendung leicht in der Meldungsübermittlung stecken bleiben und abwechselnd darauf warten, dass andere Nachrichten verarbeitet werden, und die Benutzerterminals mit Nachrichten überfluten, die zu schnell eintreffen, um verstanden zu werden.

Vermeidung

Jetzt, da Sie wissen, was hinter den Kulissen vor sich geht, kann ich Ihnen folgenden Rat geben:

  • Wählen Sie Benutzernamen und Modulnamen sorgfältig aus, um sicherzustellen, dass Sie nur die Benutzer erreichen, die die Nachricht erhalten sollen, und keine anderen. Beispiele: John_Doe.* oder *.Operations oder John_Doe.SysAdmin.
  • Erwägen Sie die Implementierung einer Liste von Benutzern ohne Sternzeichen, um jede Benachrichtigung separat zu versenden.
  • Speichern Sie die Details der Fehlermeldungen an anderer Stelle (z. B. in einem Fehlerprotokoll) und verwenden Sie s$send_message, um nur auf das Vorhandensein von Fehlern hinzuweisen.
  • Begrenzen Sie die Häufigkeit der Benachrichtigungen auf ein angemessenes Maß (vielleicht nicht mehr als einmal pro Minute).
  • Unterdrücke jede Nachricht, die mit der zuletzt gesendeten identisch ist. Die neue Nachricht würde einfach die vorherige überschreiben.

Wenn Sie weitere Vorschläge haben, schreiben Sie bitte Ihre Kommentare, damit andere sie sehen können.