Ich implementieren müssen, um einen Weg zu schlafen diesen thread, bis es Arbeit hat zu tun
Okay, also diese Frage ist nicht gerade um die thread-Verwaltung... naja, fast. Ich bin auf der Suche nach verschiedenen Lösungen, die für diese Konfiguration. Ich habe ein paar Ideen, bin aber auf der Suche nach Lösungen, die befriedigen konnten das problem. Und Wiegen die vor-und Nachteile zur Umsetzung der beste.
Hier ist die situation.
Ich habe einen manager-Anwendung, die erzeugen ein Gewinde. Dieser thread wird kontinuierlich ausgeführt und Griff die serielle Kommunikation mit boards, die an das system angeschlossen über USB. Die manager-Anwendung erleichtert die Kommunikation zwischen anderen Anwendungen auf dem system laufen, und diesen thread. Der thread muss wirklich performen zwei Dinge:
- Umfrage die Bretter für die sample-Daten über die serielle auf eine variable timer.. in der Regel etwa einmal in der minute (der serielle bus ist eher langsam, Baudrate ist 4800. Ich kann nicht kontrollieren diese)
- Erleichtern die Kommunikation mit der manager-Anwendung. (d.h. andere Anwendungen, Anfrage Beispiel die Daten, die der manager leitet die Anfrage an den thread. der thread führt die operation und liefert die Daten)
Meine ursprüngliche design war einfach und funktioniert. Verwende ich eine queue und einem mutex für manager-zu-thread-Kommunikation. So ist die Logik der thread ist wie folgt:
- Initialisierung
- Während wir nicht erhalten haben, einen shutdown-Befehl aus dem manager
- Wenn unser timer, poll, der Vorstand für die Daten
- Ansonsten schauen, um zu sehen, wenn wir eine Nachricht gesendet, indem die manager in der Warteschlange. wenn dem so ist, verarbeiten
Das problem ist, ich nicht betrachten die CPU-Auslastung. 99,9% der Zeit mein thread ist die Verarbeitung nichts und nur saugen, bis macht. Ich implementieren müssen, um einen Weg zu schlafen diesen thread, bis es Arbeit hat, das zu tun. So ein paar Ideen:
Verwenden, wählen Sie (), um zu blockieren. Dieser block kann auf den timer muss ich verwenden, und ich könnte das ändern der queue-messaging-implementation-Buchse
messaging. Anstatt also, der thread würde öffnen Sie ein client-socket, um die
manager und der manager bestehen würde, die Nachrichten über den socket an den
thread. Wählen Sie anschließend() schlafen würde, bis es die Aktivität auf den fd
oder mein timer war.
Pro: Genau die Funktionalität, die ich brauche.
Con: nicht-sockets ein bisschen die schwere Verarbeitung für die Kommunikation zu einem thread, wo Sie Speicher freigeben, schon?
Verwendung eines signal-system. (Jemand mehr wissen in Linux können Rohr bis hier mit einer Umsetzung Beispiel... ich bin mir nicht ganz sicher, wie
tun Sie es.) Aber der thread könnte schlafen für die Dauer der timer, und
wake up zu verarbeiten, wenn ein signal empfangen wurde von dem manager.
Pro: Verwaltet die aktuelle Implementierung mit shared memory
Con: Nicht sicher, wie Sie Sie umsetzen. Gibt es eine Funktion wie select (), das funktioniert mit den Signalen anstelle von fds?
Potenziell einen mutex. Ich könnte blockieren, bis ein mutex veröffentlicht wurde durch den manager.
Pro: Noch immer werden die gemeinsame Nutzung von Speicher
Nachteil: möglicherweise verschieben müssen, um timer-Verarbeitung an den manager und das ist nicht wirklich eine option, wie es andere Zeitgeber und Kritischer Arbeit ausführen.
Empfehlen Sie bitte ein und fühlen Sie sich frei zu Kritik. Ich bin offen für jede effiziente Optionen. Bitte beachten Sie aber diese läuft auf einem embedded-system, so dass Ressourcen-Nutzung ist kritisch.
- Warum nicht eine bedingte variable, wenn Sie haben zu warten, für eine Veranstaltung? Der thread ist effektiv setzen, um zu schlafen, bis die variable signalisiert durch einen anderen thread.
- Ich konnte absolut, aber der Punkt ist, ich will nicht, um die Bearbeitung etwas. Ich will nicht, um wiederholt zu prüfen, den Wert einer Variablen ändern wird, einmal pro minute. Das ist eine Menge Aufwand. Ich will den thread so zu schlafen, dass gibt es CPU-Zeit.
- Stellen Sie sicher, dass Sie dies vermeiden: stackoverflow.com/questions/3886171/...
- Warten Sie, ich glaube nicht, dass wir reden über die gleiche bedingungsvariable. Ich meinte
pthread_cond_t
, die Aussetzung der thread beim Aufrufpthread_cond_wait
, nicht beschäftigt spin. Oder bin ich Missverständnis, was? - Die queue-Implementierung ist das, was ausgeführt wird. Das Ergebnis ist der thread von ~45% der CPU-Zeit. Das ist einfach nicht akzeptabel. Die select () - Implementierung ist einfach genug zu tun, aber ich bin mir nicht sicher, ob das öffnen eines socket an einen thread ist der richtige Ansatz. Jemand mit mehr Erfahrung als mich, ist wahrscheinlich besser ausgerüstet zu beantworten.
- danke für den link. Nach dem Lesen der bugs mit pause() ich denke, ich werde entscheiden, vermeiden Sie die Verwendung des signal-system. Als meine Implementierung wäre genau das, was Sie sagen, bewirkt, dass die Unzuverlässigkeit. Ich brauche zu suspendieren, bis ein signal und dann wieder arbeiten. Danke für die info aber.
- ja, wir waren Missverständnisse untereinander. Ich Folge dir jetzt. Die bedingte würde funktionieren, für die Kommunikation mit dem manager, aber die Lösung, die ich implementieren müssen, auch muss der timer für die Abfrage, nicht nur true/false Bedingungen. Wie könnte ich implementieren Sie den timer mit
pthread_cond_t
? - Sie können sich
pthread_cond_timedwait
: pubs.opengroup.org/onlinepubs/009604599/functions/... - danke, mir war nicht bewusst _timedwait. Dies könnte eine gute Lösung sein, wie es erforderlich wäre nicht Umkodierung der manager-thread-Kommunikation. Ich lese es auf.
- Wie ist der timer implementiert? Ist es extern an die worker-Threads (wie der andere thread oder der kernel mit
setitimer
odertimer_create
), oder ist der thread nur dazu eigene Zeitmessung? - der thread hat seine eigene Zeit zu halten. als manager hat viel zu tun und es ist eigenen Timer zu führen. macht es Sinn für den thread zu behandeln, es ist ein eigenes timing.
- gut, es gibt auch andere richtige und effiziente Ansätze, die Sinn haben könnte, auch. 🙂 Allerdings, und erweitern Sie Ihren Warteschlange zu unterstützen "timed dequeue-operation" über
pthread_cond_timedwait
— in essence Martin James' Antwort — macht Sinn für Sie.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Probieren Sie etwas wie dieses, mit Semaphore:
Können Sie ersetzen
sem_wait
mitsem_timedwait
wenn Sie einen timeout.Das klassische Werkzeug für solche Situationen sind Semaphoren und nicht Mutexe oder Zustands-Variablen. Denke, von Ihnen als Token übergeben vom manager zum thread.
Den thread nutzen könnte
sem_timedwait
um sicher zu sein, wake-up einmal in eine Weile zu überprüfen, für die Daten.Vorsicht erfassen der Fehler wieder Auftritt, von
sem_
gut funktioniert, sind Sie unterbrochen werden. So haben Sie möglicherweise ein bisschen mehr, wake-ups, als man denken würde.sem_t
ist ausgelegt auf den Zweck verwendbar sein, die in der signal-Handler, dies ist ein low-level-tool von design. Das hat nichts zu tun mit "Defekten" OS und schon gar nichts zu tun mit Dijstra. In allen halte ich Ihre Bemerkung ziemlich unangebracht.Schalter POSIX message queues anstelle Ihres eigenen.
mq_timedreceive
zurück, wenn der manager sendet eine Anfrage. Wenn es mal aus, Sie haben Ihre timer-polling. Die synchonization und Sperrung kommt schon verpackt.Haben jeder thread wartet auf einen input producer-consumer-queue mit einem timeout. Wenn die Warteschlange Wartezeit aus, poll serial-link, sonst Prozess der empfangene Befehl in die Warteschlange ein. Um eine passende queue von vorne an, benötigen Sie einen aktuellen Warteschlange, (die Sie schon haben), einen mutex zum Schutz der Warteschlange Zeiger/Indizes, (die Sie schon haben), und ein semaphor, initialisiert auf 0, mit einer Wartezeit(timeout) - Funktion. Zum senden der thread eine Anfrage, sperren des mutex, drücken Sie die Anforderung, entsperren das mutex, signal semaphore. In dem thread, warten auf die semaphore, wenn warten Renditen ohne timeout, sperren des mutex, die pop-Anfrage (denn es wird immer sein), entsperren das mutex-und verarbeiten der empfangenen Anforderung. Wenn die sema warten, kehrt mit einem timeout poll der seriellen Verbindung. Wenn Sie fertig sind, Schleife um zu warten auf die semaphore wieder.
Variieren das timeout, senden Sie dem thread eine Nachricht mit dem Befehl 'EchangeWaitInterval', (sagen wir:), und die neue timeout-Intervall für die spätere wartet.
Den klassischen pthreads Ansatz wäre, um Ihre thread-block in
pthread_cond_wait()
bis der manager-thread stellt eine Nachricht in die queue und signalisiert den Zustand der variable. In diesem Fall, zum aufwachen in einer angemessenen Weise auf eine Umfrage der seriellen Geräte verwendenpthread_cond_timedwait()
statt.