6 Stimmen

Wettlaufbedingung im C-Signalhandler-Rätsel

Ich muss wissen, wie man eine Wettlaufsituation vermeidet, wenn Signale in C behandelt werden. Jedes Mal, wenn mein Programm ein Signal empfängt, möchte ich, dass es eine (globale) verkettete Liste ändert. Es ist äußerst wichtig, dass ich kein Signal verpasse, und ebenso wichtig ist es, dass die globale verkettete Liste, die ich ändere, während der Handler ausgeführt wird, nicht verändert wird.

Das Problem ist, wenn ich ein Signal empfange und den Handler starte, aber dann von einem anderen Signal unterbrochen werde. Dies (wie ich es verstehe) löst eine neue Ausführung des Signalhandlers aus, der auf denselben globalen Datensatz wirkt - nicht zulässig!

Ich kann kein Schloss verwenden, denn wenn der erste Aufruf des Handlers unterbrochen wird, wird es natürlich nie das Schloss für den unterbrechenden Handler freigeben, um es aufzunehmen. Also, wie mache ich das? Irgendwelche Ideen?

1voto

Nate Punkte 12067

Wenn Sie das Glück haben, in einer Mehrfadenumgebung zu arbeiten, ist eine der besten Möglichkeiten, die globale verkettete Liste ausschließlich von einem separaten Thread kontrollieren zu lassen. Interrupts würden Anfragen an diesen Thread anfügen (etwas, das sehr schnell ausgeführt werden würde, zum Beispiel, indem einfach ein Zeiger übergeben wird), und dann würde der Thread prozedural jede Anfrage durchgehen und die verkettete Liste ändern. Dies ermöglicht eine ausführung ohne Sperren.

Natürlich müssen Sie sich auf den Nachrichtenaustausch Ihres Betriebssystems verlassen, sodass dies möglicherweise keine Option ist.

1voto

qrdl Punkte 32507

Sie können Signale maskieren, während der Signalhandler ausgeführt wird - überprüfen Sie das sa_mask-Feld der struct sigaction, die Sie an den sigaction()-Syscall übergeben.

1voto

jcomeau_ictx Punkte 36287

Von http://users.evtek.fi/~tk/rtp/signals-programming.html:

Der Weg, um überhaupt keine Rennen zu garantieren, besteht darin, dass das System die Signalmaskierung für uns festlegt, bevor es den Signal-Handler aufruft. Dies kann gemacht werden, wenn wir den Systemaufruf sigaction() verwenden, um sowohl die Signal-Handler-Funktion ALS AUCH die Signalmaske zu definieren, die verwendet wird, wenn der Handler ausgeführt wird. Sie könnten wahrscheinlich die Bedienungsanleitung für sigaction() alleine lesen, jetzt, da Sie mit den verschiedenen Konzepten der Signalbehandlung vertraut sind. Auf alten Systemen finden Sie jedoch diesen Systemaufruf nicht, aber Sie könnten den Aufruf sigvec() finden, der eine ähnliche Funktionalität ermöglicht.

0voto

Sim Sun Punkte 537

Ich denke, Sie sollten das Signal seriell schalten, genau wie die Arbeitswarteschlange. Zum Beispiel sollten alle Signale in eine Arbeitswarteschlange (FIFO) eingereiht werden, und dann liest der ausführende Thread die Warteschlange die ganze Zeit ab. Wenn die Warteschlange nicht leer ist, wählt dieser Thread das oberste Signal aus und startet seinen Handler. Machen Sie das so weiter, bis die Warteschlange leer ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X