Beansprucht eine endlose While-Schleife CPU-Ressourcen?

Lesezeit: 7 Minuten

Soweit ich weiß, schreiben Sie Ihren Linux-Daemon, der in einer Endlosschleife auf eine Anfrage lauscht.
Etwas wie..

int main() {
    while(1) {
        //do something...
    }
}

Referenz: http://www.thegeekstuff.com/2012/02/c-daemon-process/

Ich habe gelesen, dass das Schlafen eines Programms dazu führt, dass es in den Wartemodus wechselt, damit es keine Ressourcen verbraucht.

1. Wenn ich möchte, dass mein Daemon alle 1 Sekunde nach einer Anfrage sucht, würde das Folgende Ressourcen verbrauchen?

int main() {
    while(1) {
        if (request) {
            //do something...
        }
        sleep(1)
    }
}

2. Wenn ich den Ruhezustand entferne, bedeutet das, dass der CPU-Verbrauch um 100 % steigt?

3.Ist es möglich, eine Endlosschleife zu laufen, ohne Ressourcen zu verbrauchen? Sagen Sie … wenn es nichts tut, sondern sich nur selbst wiederholt. Oder einfach schlafen(1).

Endlosschleifen und CPU-Ressourcen sind mir ein Rätsel.

  • Sleeping weist den Scheduler an, einen anderen Prozess auf der CPU anstelle Ihres Prozesses für eine bestimmte Zeitspanne laufen zu lassen (halten Sie es einfach). Ihr Programm verbraucht im Ruhezustand keine CPU-Ressourcen. Sogar das Schlafen von nur wenigen Millisekunden macht die Dinge in einer Endlosschleife glatt, wie Sie es gezeigt haben.

    – Nikolas R

    3. Dezember 2012 um 9:43 Uhr

  • Wenn du bist Hören dann sollten Sie einen Multiplexing-Systemaufruf wie verwenden poll(2) (oder die ältere, fast veraltete, select(2))

    – Basile Starynkevitch

    3. Dezember 2012 um 11:29 Uhr

Ist es möglich, eine Endlosschleife zu durchlaufen, ohne Ressourcen zu verbrauchen? Sagen Sie … wenn es nichts tut, sondern sich nur selbst wiederholt. Oder einfach schlafen(1).

Es gibt eine bessere Option.
Sie können einfach eine verwenden Semaphordie am Anfang der Schleife blockiert bleibt, und Sie können dem Semaphor signalisieren, wann immer Sie möchten, dass die Schleife ausgeführt wird.
Beachten Sie, dass dies keine Ressourcen verbraucht.

  • “wird keine Ressourcen verbrauchen” ist nicht ganz richtig … Das Erstellen eines Semaphors verwendet Kernel-Ressourcen und -Objekte und ist eine ziemlich schwere Operation. Das Warten auf die Semaphore ist eine Kernel-Modus-Operation und führt auch zu einem Kontextwechsel in den Kernel-Modus.

    – Mahmoud Al-Qudsi

    3. Dezember 2012 um 9:54 Uhr

  • Ein Semaphor wäre angemessen, wenn ein Timeout verwendet wird, aber Schlaf ist wahrscheinlich immer noch am besten. Das Semaphor ist am relevantesten, wenn Sie möchten, dass Ihr Code ausgelöst wird entweder Auszeit oder ein externes Ereignis.

    – Kevin A. Naudé

    3. Dezember 2012 um 10:01 Uhr

  • Danke für die Erwähnung von Semaphor. Das muss ich mal erkunden, wenn es soweit ist 🙂

    – ausruhen

    20. Dezember 2012 um 2:29 Uhr

Das poll und select Anrufe (von Basile Starynkevitch in einem Kommentar erwähnt) oder ein Semaphor (von Als in einer Antwort erwähnt) sind je nach den Umständen die richtigen Möglichkeiten, um auf Anfragen zu warten. Auf Betriebssystemen ohne poll oder selectso etwas ähnliches sollte es geben.

Weder sleep, YieldProcessornoch sched_yield sind aus den folgenden Gründen geeignete Möglichkeiten, dies zu tun.

YieldProcessor und sched_yield Verschieben Sie den Prozess lediglich an das Ende der ausführbaren Warteschlange, lassen Sie ihn jedoch ausführbar. Der Effekt ist, dass sie anderen Prozessen mit der gleichen oder einer höheren Priorität die Ausführung erlauben, aber wenn diese Prozesse fertig sind (oder wenn es keine gibt), dann den Prozess, der aufgerufen hat YieldProcessor oder sched_yield läuft weiter. Dies verursacht zwei Probleme. Einer ist, dass Prozesse mit niedrigerer Priorität immer noch nicht ausgeführt werden. Ein weiterer Grund ist, dass dies dazu führt, dass der Prozessor immer läuft und Energie verbraucht. Wir würden es bevorzugen, wenn das Betriebssystem erkennt, wann kein Prozess ausgeführt werden muss, und den Prozessor in einen Energiesparmodus versetzt.

sleep kann diesen Niedrigenergiezustand zulassen, aber es spielt ein Ratespiel darüber, wie lange es dauern wird, bis die nächste Anfrage eintrifft, es weckt den Prozessor wiederholt auf, wenn es nicht nötig ist, und es macht den Prozess weniger reaktionsschnell auf Anfragen, da die Der Prozess schläft bis zum Ablauf der angeforderten Zeit weiter, selbst wenn eine zu bedienende Anforderung vorliegt.

Das poll und select Anrufe sind genau für diese Situation konzipiert. Sie teilen dem Betriebssystem mit, dass dieser Prozess eine Anfrage bedienen möchte, die auf einem seiner I/O-Kanäle eingeht, ansonsten aber keine Arbeit zu erledigen hat. Dadurch kann das Betriebssystem den Prozess als nicht lauffähig markieren und den Prozessor gegebenenfalls in einen Energiesparzustand versetzen.

Die Verwendung eines Semaphors bietet das gleiche Verhalten, außer dass das Signal zum Aufwecken des Prozesses von einem anderen Prozess kommt, der den Semaphor auslöst, anstatt von einer Aktivität, die in einem I/O-Kanal entsteht. Semaphore sind geeignet, wenn das Signal, etwas zu tun, auf diese Weise ankommt; Verwenden Sie einfach einen der beiden poll oder ein Semaphor ist für Ihre Situation besser geeignet.

Die Kritik daran poll, select, oder ein Semaphor verursacht einen Aufruf im Kernel-Modus ist irrelevant, da die anderen Methoden auch Aufrufe im Kernel-Modus verursachen. Ein Prozess kann nicht alleine schlafen; es muss das Betriebssystem aufrufen, um es anzufordern. Ähnlich, YieldProcessor und sched_yield Anfragen an das Betriebssystem stellen.

Benutzer-Avatar
Kevin A. Naudé

Die kurze Antwort lautet ja – das Entfernen des Ruhezustands ergibt 100 % CPU – aber die Antwort hängt von einigen zusätzlichen Details ab. Es verbraucht die gesamte CPU, die es bekommen kann, es sei denn …

  1. Der Schleifenkörper ist trivial und wegoptimiert.
  2. Die Schleife enthält eine blockierende Operation (wie eine Datei- oder Netzwerkoperation). Der von Ihnen bereitgestellte Link schlägt vor, dies zu vermeiden, aber es ist oft eine gute Idee, zu blockieren, bis etwas Relevantes passiert.

BEARBEITEN : Für Ihr Szenario unterstütze ich den Vorschlag von @Als.

BEARBEITEN 2: Ich gehe davon aus, dass diese Antwort eine -1 erhalten hat, weil ich behaupte, dass das Blockieren von Operationen tatsächlich eine gute Idee sein kann. [If you -1, you should leave a motivation in a comment so that we all may learn something.]

Die derzeitige verbreitete Meinung ist, dass blockfreie (ereignisbasierte) E/A gut und Blockierung schlecht ist. Diese Ansicht ist zu stark vereinfacht, da davon ausgegangen wird, dass alle Software, die E/A durchführt, den Durchsatz verbessern kann, indem sie nicht blockierende Vorgänge verwendet.

Was? Behaupte ich wirklich, dass die Verwendung von nicht blockierendem IO den Durchsatz tatsächlich reduzieren kann? Ja, kann es. Wenn ein Prozess einer einzelnen Aktivität dient, ist es tatsächlich besser, Blocking IO zu verwenden, da das Blockieren von IO nur Ressourcen verbraucht, für die bereits während der Existenz des Prozesses bezahlt wurde.

Im Gegensatz dazu kann nicht blockierendes IO einen größeren festen Overhead tragen als einfaches blockierendes IO. Wenn der Prozess keine zusätzlichen E/A liefern kann, die verschachtelt werden können, bringt es nichts, wenn Sie für eine nicht blockierende Einrichtung bezahlen. (In der Praxis liegen die größten Kosten für unangemessene, nicht blockierende E/A einfach in der zusätzlichen Codekomplexität. Darüber hinaus ist dieses Thema größtenteils eine Gedankenübung.)

Beim Blockieren von IO verlassen wir uns darauf, dass das Betriebssystem die Prozesse plant, die Fortschritte machen können. Dafür ist das Betriebssystem ausgelegt.

Bei nicht blockierendem IO haben wir höhere Einrichtungskosten, können aber die Ressourcen des Prozesses und seiner Threads zwischen verschachtelter Arbeit teilen. Das Non-Blocking IO ist daher ideal für jeden Prozess, der mehreren unabhängigen Aktivitäten dient, wie z. B. einem Webserver. Der gewonnene Durchsatz ist den Fixkosten von Non-Blocking IO bei weitem überlegen.

  • Software verbessert den Durchsatz möglicherweise nicht durch die Verwendung von nicht blockierender E/A, aber sie verbessert sich immer Empfänglichkeit. Ja, Sie sollten blockieren, aber es sollte ein blockierender Aufruf sein, der auf eine Vielzahl von Ereignissen wartet, kein blockierender E/A-Aufruf, der dazu führt, dass Benutzereingaben ignoriert werden, bis die E/A abgeschlossen ist. select, poll, aio_suspend sind alles Beispiele. Sie sagen “Wenn der Prozess keine zusätzlichen IO liefern kann, die verschachtelt werden können”, aber es gibt immer mindestens eine zusätzliche Eingabe, die passieren kann … eine Benutzeranforderung zum Beenden.

    – Ben Voigt

    9. Mai 2013 um 0:29 Uhr


  • @BenVoigt Das stimmt. Interaktive Anwendungen sollten nicht auf unbestimmte Zeit blockieren, z. B. sollte ein Semaphor dann einen Timeout verwenden. Allerdings können Posix-Backend-Dienste auch dann Signale empfangen, wenn eine Blockierungsoperation durchgeführt wird. Alles in allem haben Sie einen guten Punkt angesprochen, an den Sie sich erinnern sollten – danke.

    – Kevin A. Naudé

    9. Mai 2013 um 6:10 Uhr

1363610cookie-checkBeansprucht eine endlose While-Schleife CPU-Ressourcen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy