Zum Hauptinhalt springen

Das OpenVOS-Betriebssystem bietet eine High-Level-Anwendungsprogrammierschnittstelle (API), die im Großen und Ganzen die Programmierung des Systems einfach macht. Aber manchmal wird es zu einfach - denn ein einfacher Unterprogrammaufruf einer s$...-Routine kann eine Menge Komplexität verbergen.

Dies ist der erste Teil einer unregelmäßigen Serie von Beiträgen, die Sie auf solche Fallstricke aufmerksam machen sollen, damit Sie sie in Ihren Anwendungsdesigns vermeiden können.

Die Übel der 25. Zeile Meldungen

Die Fähigkeit, eine Nachricht in die25. (oder was auch immer die unterste) Zeile eines Terminals zu schreiben, ermöglicht es einem Benutzer (oder einem laufenden Programm), andere Benutzer über ungewöhnliche Bedingungen zu informieren. Die Kommandozeilenschnittstelle ist der Befehl send_message. Der Befehl und die Benutzerprogramme rufen letztlich das API-Unterprogramm s$send_message auf. Argumente für diesen Aufruf liefern den user_name eines Empfängers, den Namen des Zielmoduls, bei dem dieser Benutzer möglicherweise angemeldet ist, den Benachrichtigungstext und einige Flags, um Aspekte des Vorgangs zu ändern. Privilegierte Aufrufer dürfen den Namen des Absenders angeben; andernfalls wird standardmäßig der user_name des sendenden Prozesses verwendet.

So weit scheint es einfach zu sein. Da der Vorgang den Zugriff auf das Terminal erfordert, das einem anderen Benutzer gehört, sendet der Kernel die Anforderung an eine Server-Warteschlange für den Prozess TheOverseer auf dem Zielmodul. Normalerweise wartet der sendende Prozess dann auf den Status der Nachrichtenzustellung, kann sich aber dafür entscheiden, nicht auf diese Antwort zu warten.

DerOverseer -Prozess für ein beliebiges Modul verfolgt alle Anmeldeprozesse und das von diesen Prozessen verwendete Terminalgerät. Wenn er eine Anforderung zum Senden einer Nachricht erhält, durchsucht er seine Liste der Prozesse und Geräte und fügt für jeden Prozess user_name, der mit dem Argument receiver_name übereinstimmt, einen Anschluss an das Endgerät des Prozesses an, öffnet den Anschluss, schreibt die Nachricht in die Benachrichtigungsleitung, schließt den Anschluss und löst den Anschluss. Wenn mehrere Prozesse mit dem Argument receiver_name übereinstimmen, wird dieser Zyklus "Anhängen/Öffnen/Schreiben/Schließen/Lösen" für jeden Prozess wiederholt.

Okay - das ist ein wenig komplizierter, als wir zuerst besprochen haben. Bei näherer Betrachtung stellen wir fest, dass ein beliebiges Modul im System Anmeldeprozesse hosten kann, bei denen das eigentliche Terminal ein Gerät auf einem anderen System/Modul ist, das Open StrataLink (OSL) zur Anmeldung über das Netzwerk (mit dem Befehl login -module) verwendet hat. Der scheinbar einfache Vorgang des Anhängens/Öffnens/Schreibens/Schließens/Abnehmens auf diesem Terminal muss nun OSL-Prozesse und Netzwerk-Remote-Prozeduraufrufe an das entfernte Modul umfassen und ist viel kostspieliger als die modulinterne Handhabung.

Die Auswirkungen werden vergrößert, wenn der Empfänger "user_name" als Starname angegeben wird, der mit mehreren oder allen angemeldeten Benutzern übereinstimmen kann. Und es wird weiter vergrößert, wenn das Zielmodul auch als Starname angegeben wird. Der schlimmste Fall wäre das Senden der Nachricht an den Benutzer "*.*" (alle Benutzer, alle Gruppen) auf Modul "*" (alle Module des aktuellen Systems).

Implementierung

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...)
      Anschluss schließen
      Anschluss abtrennen

Diese Verarbeitung wird im no_wait_mode für jedes Terminal durchgeführt, so dass
Verzögerungen (z. B. E/A-Anforderungen über das Netzwerk) nur auf die
Nachrichtenverarbeitung für dieses Terminal auswirken.   

Wenn eine Nachricht nicht innerhalb von 300 Sekunden zugestellt werden kann, wird sie geleert.

Wenn eine Anwendung diesen Mechanismus zum Melden von Fehlern verwendet und eine Flut von Fehlern auftritt, kann die Anwendung leicht in der Meldung versinken und abwechselnd auf die Verarbeitung anderer Nachrichten warten und die Benutzerterminals mit Nachrichten überschwemmen, die zu schnell eintreffen, um verstanden zu werden.

Umgehung

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

  • Erstellen Sie sorgfältig Sternnamen für Benutzernamen und Modulnamen, um sicherzustellen, dass Sie nur die Benutzer erreichen, die die Nachricht erhalten müssen, und keine anderen. Zum Beispiel: John_Doe.* oder *.Operations oder John_Doe.SysAdmin.
  • Ziehen Sie in Erwägung, eine Liste der zu benachrichtigenden Benutzer ohne Namen zu implementieren und jede Benachrichtigung separat zu senden.
  • Legen Sie die Details von Fehlermeldungen an anderer Stelle ab (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 vernünftiges Maß (vielleicht nicht mehr als einmal pro Minute).
  • Unterdrückt jede Nachricht, die mit der zuletzt gesendeten identisch ist. Die neue würde die vorherige nur überlagern.

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

© 2024 Stratus Technologies.