2010-02-08 5 views
8

Ich benutze ein Echtzeit-Signal in Linux, um über das Eintreffen neuer Daten in einer seriellen Schnittstelle informiert zu werden. Leider führt dies dazu, dass Schlafrufe unterbrochen werden, wenn ein Signal vorliegt. Kennt jemand eine Möglichkeit, dieses Verhalten zu vermeiden.Wie man die Unterbrechung von Schlafanrufen aufgrund eines Signals unter Linux vermeidet

Edit: Ich versuchte mit einem regulären Signal (SIGUSR1), aber ich bekomme das gleiche Verhalten.

Danke, Joao

Antwort

12

Vom Nanosleep manpage:

Nanosleep verzögert die Ausführung des Programms für mindestens die in * req angegebenen Zeit. Die Funktion kann früher zurückkehren, wenn ein Signal an den Prozess gesendet wurde. In diesem Fall gibt es -1 zurück, setzt errno auf EINTR und schreibt die verbleibende Zeit in die Struktur, auf die rem verweist, es sei denn, rem ist NULL. Der Wert von * rem kann dann verwendet werden, um den Nanoschlaf wieder aufzurufen und die angegebene Pause abzuschließen.

+0

Ich werde mit diesem gehen. Ich habe einen Blick in die POCO-Bibliotheken geworfen und ihre Thread :: sleep-Implementierung funktioniert so, wie Sie es beschrieben haben. Danke – jassuncao

+0

Vergessen Sie nicht, Ihre ausgewählte Antwort zu überprüfen. –

+1

werde ich nicht, aber ich bevorzuge es, eine Weile zu warten, bevor ich eine Antwort akzeptiere. – jassuncao

2

Wenn Sie wollen nicht unterbrochen werden, warum Sie die Echtzeit-Signal verwendet?

Irgendwo, entweder in Rockinds "Advanced Unix Programming" oder Steven's Buch, gab es ein Beispiel, wie man das vortäuscht. Sie notieren sich die aktuelle time_t vor dem Schlafbeginn. Nachdem der Schlaf beendet ist, überprüfen Sie, ob die erforderliche Zeit verstrichen ist. Wenn dies nicht der Fall ist, starten Sie einen neuen Schlaf. Legen Sie den Schlaf in eine Schleife, die die Zeit berechnet, die benötigt wird, um diesen Betrag zu speichern, und beendet den Vorgang, sobald die erforderliche Zeit verstrichen ist.

+0

Es gibt alle Arten von Problemen, die damit zusammenhängen, wenn sich die Systemuhr ändert. Aus diesem Grund bietet POSIX viel ausgefeiltere Uhrfunktionen als nur den "Schlaf" -Ruf, der wahrscheinlich komplett aufgegeben werden sollte ... –

7

Sie können fast alle Signale maskieren (außer SIGKILL), indem Sie sigprocmask() oder signal() aufrufen. Der erste gibt Ihnen die vorherige Maske zurück, die Sie nach sleep() wiederherstellen können. Einige Beispiele sind here. Wenn das nicht hilft, seien Sie bitte ausführlicher, welches Signal Ihren Schlaf unterbricht. Ich denke, Sie können diesen Zustand zusätzlich überprüfen ("Schlaf unterbrochen durch Signal?") Und wieder einschlafen.

+0

Ihr Beispiel-Link ist kaputt. – OxyDeadbeef

+0

Mit den Namen von Funktionen ist es nicht schwierig, andere Beispiele zu finden, z. [Einführung in die Programmierung von Unix-Signalen] (http://titania.ctie.monash.edu.au/signals/). –

2

Nun, ein Echtzeit-Signal soll den Schlaf unterbrechen. Sie könnten stattdessen ein Nicht-Echtzeit-Signal verwenden. Ein anderer Ansatz besteht darin, zu überprüfen, ob die erwartete Schlafdauer abgelaufen ist, und falls nicht, für das verbleibende Intervall zu schlafen.

+0

Danke für Ihre Antwort, aber die Verwendung eines normalen Signals unterbricht auch Schlafanrufe. – jassuncao

5

Neuere Linux-Kernel unterstützen signalfd(2). Dies ist zusammen mit sigprocmask(2) eine sehr gute Möglichkeit, die Verarbeitung von Signal- und IO-Ereignissen in einem einzigen epoll_wait(2)-Aufruf zu kombinieren.

+0

Dies ist eine wirklich hässliche und nicht portierbare Möglichkeit, etwas zu tun, das mit vollständiger Portabilität sogar auf Legacy-Systemen (dem Self-Pipe-Trick) oder auf allen modernen POSIX-konformen Systemen (mit 'pselect') leicht gemacht werden kann. –

+3

Portabilität ist ein ehrenvolles, aber nicht immer das erste Ziel. –

+0

Der einzige Grund * in diesem Fall nicht tragbar zu sein, ist eine vorzeitige Optimierung, die die Wurzel allen Übels ist. Es gibt eine riesige Herde von Linux-Schafen, die "epoll" für die Leistung missionieren, während, solange du nicht mit Hunderttausenden von Dateideskriptoren gleichzeitig klarkommst, die leere "Umfrage" niemals dein Engpass sein wird (und selbst dann wird es fast sicher nicht sein)). Trinke den Koolaid nicht. –

Verwandte Themen