Wer verwendet POSIX-Echtzeitsignale und warum?

Lesezeit: 6 Minuten

Benutzer-Avatar
Valenzelektron

Ich bin nicht verrückt, ich verstehe es wirklich nicht. Ich habe gerade eine ganze Menge Material darüber gelesen und kann den Anwendungsfall nicht herausfinden. Ich spreche nicht so sehr von der API, für die die Vorteile gegenüber Dingen wie signal() klar genug sind. Vielmehr scheinen RT-Signale dazu gedacht zu sein, vom Benutzerraum generiert zu werden, aber zu welchem ​​Zweck? Die einzige Verwendung scheint ein primitiver IPC zu sein, aber alles deutet darauf hin, dass es sich um eine lausige Form von IPC handelt (z. B. umständlich, begrenzte Informationen, nicht besonders effizient usw.).

Wo und wie werden sie eingesetzt?

Benutzer-Avatar
R.. GitHub HÖREN SIE AUF, ICE ZU HELFEN

Beachten Sie zunächst, dass Bens Antwort richtig ist. Soweit ich das beurteilen kann, besteht der gesamte Zweck von Echtzeitsignalen in POSIX darin, ein Echtzeit-Übermittlungsmechanismus für AIO, Nachrichtenwarteschlangenbenachrichtigungen, Timer-Abläufe und anwendungsdefinierte Signale (sowohl intern als auch prozessübergreifend) zu sein.

Abgesehen davon sind Signale im Allgemeinen eine wirklich schlechte Art, Dinge zu tun:

  • Signal-Handler sind asynchron, und wenn Sie nicht sicherstellen, dass sie eine asynchrone signalunsichere Funktion nicht unterbrechen, können sie nur asynchrone signalsichere Funktionen verwenden, was ihre Möglichkeiten stark einschränkt.
  • Signalhandler sind globale Zustände. Eine Bibliothek kann keine Signale verwenden, ohne einen Vertrag mit dem aufrufenden Programm darüber zu haben, welche Signale sie verwenden darf, ob sie Syscall-unterbrechend machen darf usw. Und im Allgemeinen ist der globale Zustand gerecht Eine schlechte Sache.
  • Wenn du benutzt sigwait (oder Linux signalfd -Erweiterung) und nicht Signal-Handler zum Verarbeiten von Signalen, sind sie nicht besser als andere IPC-/Benachrichtigungsmechanismen und möglicherweise noch schlechter.

Asynchrones IO wird viel besser erreicht, indem die schlecht konzipierte POSIX-AIO-API ignoriert und einfach ein Thread erstellt wird, um normales Blockieren von IO und Aufruf auszuführen pthread_cond_signal oder sem_post wenn der Vorgang beendet ist. Oder, wenn Sie sich ein wenig Leistungseinbußen leisten können, können Sie die gerade gelesenen Daten sogar über eine Pipe oder ein Socketpair an sich selbst weiterleiten und den Haupt-Thread reguläre Dateien asynchron lesen lassen select oder poll genau wie Sie Sockets/Pipes/ttys tun würden.

  • Obwohl ich das POSIX-aio nicht annähernd so sehr mag wie die überlappende Win32-E/A, ist es immer noch weitaus vorzuziehen, einen Thread für jede Operation zu erstellen. Sprechen Sie darüber, das Kind mit dem Bade auszuschütten.

    – Ben Voigt

    14. Juni 2011 um 15:56 Uhr


  • Nicht für jede Operation. Für viele Anwendungen reicht ein Thread pro Datei aus. Wenn Sie mehrere Leser/Schreiber gleichzeitig für dieselbe Datei benötigen, sollte ein Thread pro “Benutzer” der Datei (anstatt pro Zugriff) immer noch ausreichen. Die AIO-Implementierung von glibc implementiert es sowieso in etwa so; es legt nur die scheußliche POSIX AIO API oben drauf, anstatt Ihnen die Freiheit zu geben, eine gute API zu erstellen.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    14. Juni 2011 um 16:00 Uhr

  • select ist bei gewöhnlichen Dateien nutzlos. Es zeigt immer an, dass sie zum Lesen und Schreiben bereit sind. Dies ist kein Konstruktionsfehler; selbst wenn select sie nur lesbar anzeigte, wenn Daten sofort aus dem Cache gelesen werden konnten (oder schreibbar, wenn freier Cache-Speicher verfügbar war), würde es eine Race-Bedingung geben – danach select zurückgegeben, der Cache-Verfügbarkeitsstatus könnte sich ändern und read/write könnte im Kernelspace schlafen. Eine alternative Lösung wäre natürlich mmap und mlock (und fallocatewenn Sie schreiben) den Teil der Datei, auf den Sie zugreifen möchten, verwenden Sie dann normales IO.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    14. Juni 2011 um 16:44 Uhr

  • @R: Aber mmap und mlock blockieren, und ich glaube nicht, dass es eine asynchrone Version dieser Systemaufrufe gibt.

    – Ben Voigt

    14. Juni 2011 um 17:45 Uhr

  • Wenn sie normal gelesen werden, kann Ihr Programm lange einfrieren, wenn sich die Datei auf einem langsamen Medium (z. B. einer optischen Disc mit Kratzern) oder NFS befindet. Für interaktive Apps oder Server, die mehrere Clients von einem einzigen Thread aus handhaben, ist dies möglicherweise nicht akzeptabel. Das Problem mit mmap und mlock Das Schlafen im Kernelspace kann mit einem dedizierten Thread (oder sogar einem separaten Prozess) gelöst werden, um das Sperren durchzuführen (wenn eine gemeinsam genutzte Zuordnung von einem Prozess gesperrt ist, sollte sie immer für andere Prozesse ausgetauscht werden, die sie ebenfalls zuordnen).

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    14. Juni 2011 um 19:36 Uhr

Asynchrone E/A.

Echtzeitsignale sind der Mechanismus für den Kernel, um Ihr System zu informieren, wenn eine E/A-Operation abgeschlossen ist.

struct aiocb stellt die Verbindung zwischen einer asynchronen E/A-Anforderung und einer Signalnummer her.

  • Beachten Sie, dass dies nicht bedeutet, dass dies eine gute Vorgehensweise ist. Siehe meine Antwort.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    14. Juni 2011 um 15:36 Uhr

  • Daher sollten die Echtzeitsignale nicht vom normalen Benutzer verwendet werden (und ich meine das Senden und || Verarbeiten von Echtzeitsignalen).

    – Bionix1441

    27. September 2016 um 14:09 Uhr

Es ist eine alte Frage, aber immer noch.

POSIX-Threads unter Linux in glibc (NPTL) werden mit zwei Echtzeitsignalen implementiert. Sie sind vor dem Benutzer verborgen (durch Anpassen der Min/Max-Zahlenkonstanten). Alle Ereignisse, bei denen der Bibliotheksaufruf an alle Threads weitergegeben werden muss (wie z setuid) erfolgen über diese: Der aufrufende Thread sendet ein Signal an alle Threads, um die Änderung zu übernehmen, wartet auf eine Bestätigung und fährt fort.

Es gibt andere Gründe, die Echtzeitsignale zu verwenden. Ich habe eine App, die mit einer Vielzahl externer Geräte interagiert, und zwar durch eine Kombination von Mitteln (serieller Port IO, sogar direkte Adressierung einiger Karten, die älter sind als die meisten Leute, die Sie kennen). Dies ist per Definition eine “Echtzeit”-App – sie interagiert mit der realen Welt, in realer Weltzeit, nicht in “Computerzeit”.

Vieles von dem, was es tut, ist in einem Daemon-Prozess, der sich in einer Hauptschleife befindet: Behandlung eines Ereignisses, Lesen von Informationen, Schreiben von Ergebnissen an serielle Ports, Speichern von Dingen in der Datenbank und so weiter und Schleifen für ein anderes Ereignis. Andere Prozesse auf der Maschine (Benutzerprozesse) lesen die Informationen aus der DB, zeigen sie an und so weiter. Der Benutzer in diesen anderen Prozessen kann verschiedene Signale an den Daemon senden, um ihn auf verschiedene Zustände aufmerksam zu machen: Stopp, geänderte Eingabedaten und so weiter. Zum Beispiel sendet der Benutzerprozess ein “Stop”-Signal, die Signal-Handler-Routine des Daemons hat ungefähr 2 Codezeilen und setzt eine Flag-Variable. Wenn der Daemon eine Chance bekommt und es bequem ist, stoppt er. Der “Interrupt”-Code ist sehr einfach, schnell und nicht invasiv. Aber es erfüllt den Zweck, erfordert keine komplexen IPC-Strukturen und funktioniert einwandfrei.

Also, ja, es gibt Gründe für diese Signale. In Echtzeitanwendungen. Bei richtiger Handhabung funktionieren sie einwandfrei, danke.

1374100cookie-checkWer verwendet POSIX-Echtzeitsignale und warum?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy