Wenn mehr als ein Prozess von einem seriellen Gerät (/ dev / ttyXX) gelesen wird, ist es so, dass beide Prozesse nicht alle Daten erhalten können - die Daten werden in irgendeiner Weise zwischen ihnen aufgeteilt. Ich möchte ein Programm schreiben, das von einem seriellen Gerät liest, mehrere Master / Slave-Paare erstellt und dann Programmen, die vom seriellen Gerät gelesen wurden, stattdessen das Lesen von den Pty-Dateien ermöglicht, damit alle Leseprozesse die Daten empfangen vom seriellen Gerät und haben die ptys handeln wie das serielle Gerät in dem Sinne, dass, wenn sie beginnen, von der Pty lesen sie nur die neuesten Daten. Mit anderen Worten, Sie werden keine Daten bekommen, die geschrieben wurden, bevor Sie mit dem Lesen begonnen haben (es ist meine Erfahrung, dass / dev / ttyXX-Geräte funktionieren, oder zumindest das RS-232-Anemometer, von dem ich lese). Benannte Pipes können diese Semantik nachahmen, indem sie SIGPIPE abfangen, um zu bestimmen, dass es keinen Reader gibt, und daher können wir wählen, nicht in diese bestimmte benannte Pipe zu schreiben. Einige Binärdateien, die für die Verwendung von Terminals geschrieben wurden, können jedoch bei der Kommunikation mit Named Pipes fehlschlagen, da die Überprüfung auf isatty () und die Fehlernummer bei Aufrufen wie tcsetattr () zu fehlerhaften Bedingungen führen können. Der Schlüssel hier ist, in der Lage zu sein, vorhandene Binaries zu verwenden, die für ein Terminal geschrieben wurden.
Wenn ich also feststellen kann, wann die Slave-Seite der Pty zum Lesen geöffnet ist, sollte dies ungefähr die gleiche Semantik ergeben, da es im Named-Pipe-Fall kein SIGPIPE gibt. Ich stelle fest, dass HP-UX TIOCTRAP als einen ioctl () Befehl hat, der genau das zu tun scheint, was ich will, aber leider ist es unter Linux nicht verfügbar.
Ich habe Referenzen seit Tagen gelesen und die Anzahl der Optionen für diese Art von Sache ist atemberaubend. Die Antwort könnte in den Terminal-Einstellungen, blockierendem / nicht-blockierendem Verhalten, der Einstellung von Puffergrößen irgendwo, Zuständen, die von poll () / select () gemeldet werden, oder einer Kombination liegen. Ich kann jedoch nichts finden. Ich frage mich, ob es möglich ist, dass ich meinen eigenen Gerätetreiber schreiben muss, aber es scheint, dass ich in der Lage sein sollte, das zu tun, ohne so weit zu gehen.
Also zur Klarstellung:
- Die Frage ist: Wie kann ich erkennen, wenn jemand die Slave-Seite eines pty (Pseudo-Terminal) in Linux öffnet?
- Ich möchte, dass ein Leser die Slave-Seite der Pty öffnet, um Daten zu erhalten, die streng geschrieben werden, nachdem der Leser die Pty öffnet (wenn mein Multi-Writing-Prozess nur Daten für eine Weile schreibt, bevor der Leser die Slave-Seite öffnet, werden die Daten gepuffert und schließlich wird der Schreiber blockieren und der Slave-Leser wird beim Öffnen sofort alle gepufferten Daten erhalten - dies ist nicht wünschenswert, da ich möchte, dass nur Daten empfangen werden, die in unmittelbarer zeitlicher Nähe erzeugt wurden.
- Es muss eine pty sein, nicht eine benannte Pipe, ein Socket usw., da isatty () und tcsetattr () usw. in Ordnung sein müssen, damit vorhandene Binärdateien funktionieren
Der Grund, warum Sie das nicht finden können, ist, dass es keine dokumentierte Schnittstelle gibt, die dies spezifisch zulässt. Es gibt jedoch einen Trick, mit dem Sie es tun können. Nach dem Öffnen des Pseudo-Terminal-Masters (hier als Dateideskriptor ptm
angenommen), öffnen und schließen Sie sofort die Slave-Seite:
Dies setzt das HUP-Flag auf dem tty-Master. Sie rufen das HUP-Flag nun regelmäßig mit poll()
ab (etwa wenn Daten aus Ihrer Datenquelle eintreffen):
Wenn der Leser jemals verschwindet, wird POLLHUP
erneut gesetzt.
In Ihrem Fall müssen Sie sich wahrscheinlich nicht einmal von einer Schleife zur nächsten erinnern, ob eine bestimmte pty über ein Lesegerät verfügt - blockieren Sie einfach read()
in Ihrer Datenquelle und dann, wenn Daten verfügbar sind, gleichzeitig poll()
all Ihrer Master-Ttys und senden Sie die Daten an einen von ihnen, die nicht POLLHUP
gesetzt haben.
Fügen Sie eine Inotify-Uhr auf dem Slave hinzu und fragen Sie danach. Sie können ein inotify-Ereignis bei open erhalten. Sie können dann den Inotify-Dateideskriptor und den Master-Pty-Dateideskriptor abfragen. Sie können ein inotify-Ereignis für open (IN_OPEN) abrufen. Dadurch wird die Abfrage entsperrt, wenn die Slave-Seite geöffnet wird.
Tags und Links linux file file-descriptor pty