3 Stimmen

select() innerhalb einer Endlosschleife verbraucht auf einer virtuellen RHEL 4.8-Maschine deutlich mehr CPU als auf einer Solaris 10-Maschine

Ich habe eine Daemon-App in C geschrieben und läuft derzeit ohne bekannte Probleme auf einem Solaris 10-Rechner. Ich bin gerade dabei, sie auf Linux zu portieren. Ich musste nur minimale Änderungen vornehmen. Beim Testen hat sie alle Testfälle bestanden. Es gibt keine Probleme mit seiner Funktionalität. Wenn ich mir jedoch die CPU-Auslastung im Leerlauf auf meinem Solaris-Rechner ansehe, verbraucht er etwa 0,03 % CPU. Auf der virtuellen Maschine, auf der Red Hat Enterprise Linux 4.8 läuft, verbraucht derselbe Prozess die gesamte verfügbare CPU (normalerweise irgendwo im Bereich von 90 % und mehr).

Mein erster Gedanke war, dass etwas mit der Ereignisschleife nicht stimmen kann. Die Ereignisschleife ist eine Endlosschleife ( while(1) ) mit einem Aufruf an select() . Der Zeitablauf ist so eingestellt, dass timeval.tv_sec = 0 y timeval.tv_usec = 1000 . Dies scheint angemessen für das, was der Prozess tut. Als Test habe ich die timeval.tv_sec auf 1. Auch nachdem ich das getan hatte, sah ich das gleiche Problem.

Gibt es etwas, das ich bei der Funktionsweise von select unter Linux im Vergleich zu Unix übersehe? Oder funktioniert es anders mit einem Betriebssystem, das auf einer virtuellen Maschine läuft? Oder gibt es vielleicht etwas anderes, das ich völlig übersehe?

Und noch etwas: Ich bin mir nicht sicher, welche Version von Vmware Server verwendet wird. Er wurde allerdings erst vor etwa einem Monat aktualisiert.

5voto

Zan Lynx Punkte 51045

Ich glaube, dass Linux die verbleibende Zeit zurückgibt, indem es sie in den time-Parameter des select()-Aufrufs schreibt, während Solaris dies nicht tut. Das bedeutet, dass ein Programmierer, der die POSIX-Spezifikation nicht kennt, den Zeitparameter zwischen Aufrufen von select möglicherweise nicht zurücksetzt.

Dies würde dazu führen, dass für den ersten Anruf eine Zeitüberschreitung von 1000 usec und für alle weiteren Anrufe eine Zeitüberschreitung von 0 usec gilt.

0 Stimmen

Genial! Das war das Problem. Danke!

1voto

Giuseppe Guerrini Punkte 4102

Wie Zan Lynx sagte, wird das Zeitintervall durch select unter Linux verändert, daher sollten Sie den korrekten Wert vor jedem select-Aufruf neu zuweisen. Außerdem schlage ich vor, zu prüfen, ob sich ein Teil des Dateideskriptors in einem bestimmten Zustand befindet (z.B. Dateiende, Peer-Verbindung geschlossen...). Vielleicht zeigt die Portierung einen latenten Fehler in der Analyse der zurückgegebenen Werte (FD_ISSET und so weiter). Auch mir ist das vor einigen Jahren bei der Portierung eines select-gesteuerten Zyklus passiert: Ich benutzte den zurückgegebenen Wert auf die falsche Art und Weise, und ein geschlossenes fd wurde dem rd_set hinzugefügt, was zum Fehlschlagen von select führte. Auf der alten Plattform wurde das falsche fd verwendet, um einen höheren Wert als maxfd zu haben, also wurde es ignoriert. Aufgrund desselben Fehlers erkannte das Programm den select-Fehler nicht (select() == -1) und führte eine Endlosschleife durch.

Auf Wiedersehen!

0 Stimmen

Das ist ein sehr guter Punkt... Ich werde mich jetzt damit befassen. Danke!

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