Obwohl dieses Thema in diesem Forum und allen anderen Foren schon oft diskutiert wurde, habe ich noch Zweifel. Bitte helfen.
Wie funktioniert das do{} while(0)
im Makro im Linux-Kernel?
Zum Beispiel
Wie deaktiviert es Preempt?
%Vor%Wie wird es neu geplant?
Ähnlich habe ich Makros für Mutex-Sperren und andere auch gesehen. Wie hilft das? Ich verstehe für folgendes Problem, aber nicht für die obigen Beispiele.
%Vor%Bearbeiten:
Was ist mit dem folgenden Code für rt_mutex_lock
?
Ich bin verwirrt, weil rt_mutex_deadlock_account_lock
an zwei Stellen im Kernel definiert ist:
In kernel/rtmutex-debug.c
:
In kernel/rtmutex.h
:
Im neuen Kernel 2.6.35.4 im i2c-Treiber hat rt_mutex_lock(&adap->bus_lock);
den mutex_lock()
ersetzt. Wie schließt sich das dann?
@Kragen hat geantwortet, was das do ... while construct ist - es macht im Grunde ein Makro viel sicherer zu benutzen.
Ich glaube jedoch nicht, dass es die Frage "Wie funktioniert das?" beantwortet:
%Vor%Das Makro ist definiert als nichts tun . Warum möchtest du nichts tun?
In einigen Fällen möchten Sie ein Makro als Platzhalter verwenden, um etwas zu tun. Beispielsweise könnten Sie Code auf einem System schreiben, bei dem "preempt" kein Problem ist, aber Sie wissen, dass der Code möglicherweise in ein System portiert wird, in dem "preempt" eine spezielle Behandlung erfordert. Sie verwenden also ein Makro überall dort, wo das zweite System es benötigt (so dass die Handhabung später leicht möglich ist), aber für das erste System definieren Sie dieses Makro dann als leeres Makro.
In einigen Fällen möchten Sie vielleicht eine Aufgabe ausführen, die aus verschiedenen Teilen besteht (z. B. START_TABLE (); TABLE_ENTRY (1); TABLE_ENTRY (2); END_TABLE ();). Dies macht eine schöne, saubere, klare Implementierung Ihres Tisches. Aber dann finden Sie, dass Sie das END_TABLE () Makro wirklich nicht benötigen. Um den Client-Code sauber zu halten, lassen Sie das Makro definiert und definieren Sie es einfach, um nichts zu tun. Auf diese Weise haben alle Ihre Tabellen eine END_TABLE und der Code ist einfacher zu lesen.
Ein ähnlicher Fall kann mit zwei Zuständen auftreten (aktivieren / deaktivieren), wobei ein Zustand das Makro benötigt, um etwas zu tun, aber der andere Zustand passiert nur standardmäßig, so dass die Implementierung von einem "leer" ist - Sie immer noch Verwenden Sie das Makro, weil es den Client-Code leichter verständlich macht, da es explizit die Orte angibt, an denen Dinge aktiviert oder deaktiviert sind.
IIRC Die Verwendung der Do-while-Funktion in Makros bewirkt, dass sie eher wie ein normaler Funktionsaufruf aussehen. Es gibt einige subtile Syntax-Probleme im Zusammenhang mit unverbundenen if-Anweisungen und solchen Dingen. Ohne das Do-while könnte das Makro wie ein normaler Funktionsaufruf aussehen, würde aber anders funktionieren.
Ich würde vermuten, dass in diesem Fall diese Makros verwendet werden, so dass bestimmte Funktionsaufrufe zu nichts kompilieren; Es sieht so aus, als wäre es das, was man bekommt, wenn CONFIG_PREEMPT
nicht gesetzt ist, so dass bestimmte Teile des Kernels, die nur für die Vorbelegung notwendig sind, einfach ohne sie verschwinden. Diese Schleifen verhindern also nicht, dass irgendetwas vorgemerkt oder neu geplant wird; Es wird eine andere Definition (wahrscheinlich eine echte Funktion) an anderer Stelle in der Kernel-Quelle geben.