- Wie kann am besten gesteuert werden, an welchen Thread ein Signal gesendet wird?
Wie @ zoli2k angedeutet hat, ist es eine gute Technik, explizit einen einzelnen Thread für alle zu behandelnden Signale (oder eine Reihe von Threads mit jeweils spezifischen Signalverantwortlichkeiten) zu benennen.
- Was ist der beste Weg, um einem anderen Thread (der möglicherweise gerade beschäftigt ist) mitzuteilen, dass das Signal angekommen ist? [...]
- Wie kann ich sicher damit umgehen, dass die Information, dass ein Signal aufgetreten ist, an andere Threads weitergegeben wird? Muss dies im Signalhandler geschehen?
Ich werde nicht "am besten" sagen, aber hier ist meine Empfehlung:
Blockieren Sie alle gewünschten Signale main
, damit alle Threads diese Signalmaske erben. Stellen Sie dann den speziellen Signalempfangsthread als signalgesteuerte Ereignisschleife her und senden Sie neu angekommene Signale als eine andere Intra-Thread-Kommunikation aus .
Der einfachste Weg, dies zu tun, besteht darin, dass der Thread Signale in einer Schleife mit sigwaitinfo
odersigtimedwait
akzeptiert . Der Thread konvertiert dann die Signale irgendwie, sendet möglicherweise eine pthread_cond_t
, weckt andere Threads mit mehr E / A auf und stellt einen Befehl in eine anwendungsspezifische thread-sichere Warteschlange, was auch immer.
Alternativ könnte der spezielle Thread die Übermittlung von Signalen an einen Signalhandler ermöglichen und die Übermittlung für die Übermittlung nur entlarven, wenn sie bereit sind, Signale zu verarbeiten. (Die Signalübertragung über Handler ist jedoch tendenziell fehleranfälliger als die Signalakzeptanz über die sigwait
Familie.) In diesem Fall führt der Signalhandler des Empfängers eine einfache und asynchronsignalsichere Aktion aus: Setzen von sig_atomic_t
Flags, Aufrufen sigaddset(&signals_i_have_seen_recently, latest_sig)
, write
() eines Bytes zu einer nicht blockierenden Selbstleitung usw. Dann kommuniziert der Thread zurück in seiner maskierten Hauptschleife den Empfang des Signals an andere Threads wie oben.
( UPDATED @caf weist zu Recht darauf hin, dass sigwait
Ansätze überlegen sind.)
sigwaitinfo()
(odersigtimedwait()
) durchlaufen und diese dann wie im letzten Absatz beschrieben an den Rest der Anwendung weitergeleitet.Gemäß dem POSIX-Standard sollten alle Threads mit derselben PID im System
pthread_sigmask()
angezeigt werden. Mit können Sie die Signalblockierungsmaske für jeden Thread definieren.Da es nur einen Signalhandler pro PID definieren darf, bevorzuge ich es, alle Signale in einem Thread zu verarbeiten und zu senden,
pthread_cancel()
wenn ein laufender Thread abgebrochen werden muss. Dies ist der bevorzugte Weg,pthread_kill()
da damit Bereinigungsfunktionen für die Threads definiert werden können.Auf einigen älteren Systemen haben die laufenden Threads aufgrund der fehlenden ordnungsgemäßen Kernelunterstützung möglicherweise eine andere PID als die PID des übergeordneten Threads. Siehe FAQ zur Signalverarbeitung mit linuxThreads unter Linux 2.4 .
quelle
make menuconfig
mit dem frisch geklonten Git-Master-Zweig von uClibc zu laufen . Es gibt eine Wahl zwischen den alten LinuxThreads und der neueren NPTL als POSIX-Thread-Implementierungen, aber die Hilfe ab dem Jahr 2012 rät immer noch davon ab, NPTL zu wählen. Daher ist es in modernen eingebetteten Linux-Systemen immer noch üblich, dass die veraltete LinuxThreads-Implementierung verwendet wird, selbst wenn auf dem System ein ausreichend aktueller Linux-Kernel ausgeführt wird.Wo ich bisher bin:
Ich habe noch zu sortieren bekam
signal
vssigaction
,pselect
,sigwait
,sigaltstack
, und eine ganze Reihe anderer Stücke von POSIX (und Nicht-POSIX) API.quelle
IMHO, Unix V-Signale und Posix-Threads mischen sich nicht gut. Unix V ist 1970. POSIX ist 1980;)
Es gibt Stornierungspunkte, und wenn Sie Signale und pthreads in einer Anwendung zulassen, werden Sie schließlich Schleifen um jeden Anruf schreiben, die überraschenderweise EINTR zurückgeben können.
In den (wenigen) Fällen, in denen ich Multithreading unter Linux oder QNX programmieren musste, habe ich alle Signale für alle (außer einem) Thread ausgeblendet.
Wenn ein Unix V-Signal eintrifft, wechselt der Prozess den Stapel (das war in Unix V so viel Parallelität, wie Sie innerhalb eines Prozesses erreichen konnten).
Wie die anderen Beiträge hier andeuten, könnte es jetzt möglich sein, dem System mitzuteilen, welcher Posix-Thread das Opfer dieses Stapelwechsels sein soll.
Sobald Sie es geschafft haben, Ihren Signal-Handler-Thread zum Laufen zu bringen, bleibt die Frage, wie Sie die Signalinformationen in etwas Zivilisiertes umwandeln können, das andere Threads verwenden können. Eine Infrastruktur für die Kommunikation zwischen Threads ist erforderlich. Ein nützliches Muster ist das Akteurmuster, bei dem jeder Ihrer Threads ein Ziel für einen in Bearbeitung befindlichen Messaging-Mechanismus ist.
Anstatt andere Threads abzubrechen oder zu beenden (oder andere seltsame Dinge), sollten Sie versuchen, das Signal aus dem Signal-Kontext in Ihren Signal-Handler-Thread zu leiten und dann mithilfe Ihrer Kommunikationsmechanismen für das Akteurmuster semantisch nützliche Nachrichten an diese Akteure zu senden. Wer braucht die signalbezogenen Informationen.
quelle