Warum ist der flüchtigen brauchte, in C?
Warum ist volatile
benötigt in C? Für was wird es verwendet? Was wird Sie tun?
InformationsquelleAutor | 2008-10-29
Du musst angemeldet sein, um einen Kommentar abzugeben.
Warum ist volatile
benötigt in C? Für was wird es verwendet? Was wird Sie tun?
InformationsquelleAutor | 2008-10-29
Du musst angemeldet sein, um einen Kommentar abzugeben.
Volatile weist den compiler nicht optimieren, was zu tun hat mit dem volatile-variable.
Gibt es nur einen Grund, es zu verwenden: Wenn Sie die Schnittstelle mit hardware.
Lassen Sie uns sagen, Sie haben ein kleines Stück hardware zugeordnet ist, in den RAM-Speicher irgendwo, und das hat zwei Adressen: eine Kommando-port und data-port:
Nun wollen Sie senden Befehl:
Sieht einfach, aber es kann fehlschlagen, weil der compiler ist frei, um die Reihenfolge zu ändern, in der Daten und Befehle geschrieben werden. Dies würde dazu führen, dass unsere kleine gadget, um Befehle mit den vorherigen Daten-Wert. Werfen Sie auch einen Blick auf das warten, während die busy-loop. Dass man optimiert. Der compiler wird versuchen, schlau zu sein, lies den Wert aus isbusy nur einmal und dann in einer endlos-Schleife. Das ist nicht, was Sie wollen.
Dem Weg, dies zu umgehen, ist zu erklären, dass die Zeiger gadget als flüchtig. Auf diese Weise wird der compiler gezwungen, das zu tun, was Sie schrieb. Sie können nicht entfernen Sie die Speicher-Zuweisungen, kann es nicht-cache-Variablen in Registern und Sie können nicht ändern die Reihenfolge der Aufgaben entweder:
Dies ist die richtige version:
ja, sollten Sie erklären Dinge, die mit einem festen register Größe, aber hey - es ist nur ein Beispiel.
Flüchtig ist auch nötig, threaded code, wenn Sie spielen mit Daten, die nicht Parallelität geschützt. Und ja, es sind die gültigen Zeiten zu tun, können Sie zum Beispiel schreiben Sie eine thread-sichere zirkuläre message queue ohne explizite Parallelität Schutz, aber es müssen volatile.
Lesen Sie die C-Spezifikation härter. Volatile hat nur definiertem Verhalten auf memory-mapped-device I/O oder memory berührt durch eine asynchrone Unterbrechung der Funktion. Es sagt nichts über threading und ein compiler optimiert das Weg Zugriff auf den Speicher berührt durch mehrere threads konform.
völlig falsch. traurig 17 Personen wissen es nicht. volatile ist ein Speicher Zaun. es ist nur im Zusammenhang mit Vermeidung von code-elision bei der Optimierung basiert auf der Annahme von nicht sichtbaren Nebenwirkungen.
InformationsquelleAutor Nils Pipenbrinck
volatile
in C tatsächlich kam in Existenz für den Zweck des nicht-Zwischenspeichern der Werte der Variablen automatisch. Es wird Ihnen sagen, die Maschine nicht zum cache den Wert dieser variable. Es wird also der Wert der gegebenenvolatile
Variablen aus dem Arbeitsspeicher jedes mal, es trifft es. Dieser Mechanismus wird verwendet, weil jederzeit der Wert kann geändert werden durch das OS oder irgendwelche unterbrechen. Also mitvolatile
wird uns helfen, den Zugriff auf den Wert von neuem, jedes mal.Ins Dasein kam? War nicht flüchtigen` ursprünglich entlehnt aus C++? Naja, ich glaube mich zu erinnern...
Dies ist nicht flüchtig - Sie verbieten auch einige nachbestellen wenn der name als flüchtig..
Der Zweck der
volatile
war, um es möglich für Compiler zum optimieren von code, während immer noch so dass Programmierer zu erreichen, die Semantik, die erreicht würde, ohne solche Optimierungen. Die Autoren der Norm zu erwarten, dass die Qualität Implementierungen unterstützen würden, unabhängig von der Semantik nützlich waren, aufgrund Ihrer Ziel-Plattformen und Anwendungs-Felder, und nicht erwarten, dass die compiler-Autoren würden versuchen, bieten die niedrigste Qualität-Semantik, die dem Standard entsprechen und nicht 100% dumm (beachten Sie, dass die Autoren der Norm explizit zu erkennen in der Logik......dass es möglich ist, für eine Umsetzung zu entsprechen, ohne von gut genug Qualität, um tatsächlich für jeden Zweck geeignet, aber Sie denken, es ist nicht notwendig, um zu verhindern, dass).
InformationsquelleAutor Manoj Doubts
Andere Verwendung für
volatile
ist signal-Handler. Wenn Sie code wie diesen:Ist der compiler erlaubt zu bemerken die Schleife Körper nicht berühren
quit
Variablen und konvertieren Sie die Schleife, um einewhile (true)
Schleife. Auch wenn diequit
variable auf die signal-handler fürSIGINT
undSIGTERM
; der compiler hat keine Möglichkeit zu wissen, dass.Jedoch, wenn die
quit
variable deklariert istvolatile
der compiler gezwungen ist, laden Sie es jedes mal, weil es geändert werden kann anderswo. Das ist genau das, was Sie wollen in dieser situation.Es bedeutet, was es sagt: Jedes mal, wenn der code prüft den Wert, es wird neu geladen. Ansonsten ist der compiler darf annehmen, dass Funktionen, die nicht mehr eine Referenz auf die variable kann nicht geändert werden, so vorausgesetzt, als CesarB beabsichtigt, dass die obige Schleife nicht
quit
der compiler optimieren kann es sich in einer Konstanten Schleife, vorausgesetzt, es gibt keine Möglichkeit fürquit
geändert werden zwischen den Iterationen. N. B.: Dies ist nicht unbedingt ein guter Ersatz für die eigentliche threadsicher Programmieren.wenn beenden Sie eine Globale variable ist, dann wird der compiler ist nicht die Optimierung der while-Schleife, richtig ?
Nein, der compiler kann immer davon ausgehen, dass der code ist single-threaded, wenn nichts anderes gesagt wird. Das heißt, in der Abwesenheit von
volatile
oder andere Marker, es wird davon ausgegangen, dass nichts außerhalb der Schleife ändert, die variable einmal geht es in die Schleife, selbst wenn es eine Globale variable.Ja, versuchen Sie zum Beispiel kompilieren
extern int global; void fn(void) { while (global != 0) { } }
mitgcc -O3 -S
und betrachten Sie die resultierende assembly-Datei auf meinem Rechner tut esmovl global(%rip), %eax
;testl %eax, %eax
;je .L1
;.L4: jmp .L4
, das ist eine Endlosschleife, wenn das Globale ist nicht null. Dann versuchen Sievolatile
und den Unterschied sehen.InformationsquelleAutor CesarB
volatile
sagt dem compiler, dass die variable kann geändert werden, durch andere Mittel, als den code, der darauf zugreift. z.B., es kann eine I/O-mapped-Speicherbereich. Wenn dies nicht angegeben ist in solchen Fällen, einige variable zugreift, kann optimiert werden, z.B. kann Ihr Inhalt in einem register und die Speicher-Position, die nicht Lesen und wieder an.InformationsquelleAutor Chris Jester-Young
Finden Sie in diesem Artikel von Andrei Alexandrescu, "volatile - Multithread-Programmer ' s Best Friend"
Den Artikel gilt für beide
C
undC++
.Siehe auch den Artikel "C++ und die Tücken des Double-Checked Locking" von Scott Meyers und Andrei Alexandrescu:
Nach dem ersten Artikel, "Wenn Sie das volatile-modifier auf eine variable, der compiler nicht-cache -, dass die Variablen in Registern — jeder Zugriff auf die eigentliche Speicherposition der Variablen." Auch der in §6.7.3.6 der c99-standard heißt es: "Ein Objekt mit volatile-qualifiziert Typ kann geändert werden in die Wege unbekannt sind, die der Durchführung oder anderen unbekannten Nebenwirkungen." Es impliziert ebenfalls, dass volatile-Variablen dürfen nicht in Registern zwischengespeichert werden und dass alle lese-und Schreibvorgänge ausgeführt werden müssen, um die relative Reihenfolge Punkte, dass Sie in der Tat zu beobachten.
Letzterer Artikel besagt in der Tat ausdrücklich, dass Sie liest, sind die Nebenwirkungen. Ersteres zeigt, dass liest kann nicht durchgeführt werden, außerhalb der Reihenfolge, aber nicht scheinen, um auszuschließen, die Möglichkeit von Ihnen erstellte zusammen.
"der compiler ist nicht gestattet, den cache in ein register" - die Meisten RISC-arcitectures ae-register-Maschinen, so dass jede read-modify-write " zum cache das Objekt in einem Register.
volatile
garantiert nicht Unteilbarkeit.Be-etwas in ein register ist nicht dasselbe wie caching. Caching würde auch auf die Anzahl der Lasten, Filialen oder Ihr timing.
InformationsquelleAutor Robert S. Barnes
Meine einfache Erklärung ist:
In einigen Szenarien, basierend auf der Logik oder der code, der compiler-Optimierung von Variablen, die es denkt, nicht ändern. Die
volatile
- Schlüsselwort verhindert, dass eine variable optimiert.Beispiel:
Aus der obige code kann der compiler denken
usb_interface_flag
ist definiert als 0, und das in der while-Schleife wird null sein, für immer. Nach der Optimierung, die der compiler wird es behandelt, alswhile(true)
alle die Zeit, was in einer unendlichen Schleife.Um zu vermeiden, diese Arten von Szenarien erklären wir, die Flagge, die als flüchtige, sagen wir, compiler, dass dieser Wert kann geändert werden, indem eine externe Schnittstelle oder anderen Modul des Programms, d.h., bitte nicht optimieren. Das ist der Anwendungsfall für volatile.
InformationsquelleAutor Venkatakrishna Kalepalli
Einen marginalen nutzen für volatile ist die folgende. Angenommen, Sie möchten berechnen Sie die numerische Ableitung einer Funktion
f
:Das problem ist, dass
x+h-x
ist in der Regel nicht gleichh
aufgrund roundoff Fehler. Denken Sie daran : wenn Sie zieht sehr nah zahlen, verlieren Sie eine Menge von signifikanten stellen, die ruinieren kann die Berechnung der Ableitung (denke 1.00001 - 1). Ein möglicher workaround könnte seinaber je nach Plattform-und compiler-Schalter, die zweite Zeile der Funktion kann ausgelöscht werden durch ein aggressiv optimierender compiler. So schreiben Sie statt
um den compiler zu zwingen Lesen Sie die memory location mit hh, der Verzicht auf eine eventuelle Optimierungs-Möglichkeit.
h
oderhh
im Derivat der Formel? Wennhh
berechnet wird die Letzte Formel, die es verwendet, wie die erste, mit keinen Unterschied. Vielleicht sollte(f(x+h) - f(x))/hh
?Der Unterschied zwischen
h
undhh
ist, dasshh
abgeschnitten, einige negative Potenz von zwei ist durch den Betriebx + h - x
. In diesem Fallx + hh
undx
unterscheiden sich genau durchhh
. Sie können auch Ihre Formel, es wird das gleiche Ergebnis, dax + h
undx + hh
gleich sind (es ist der Nenner, das ist hier wichtig).Ist nicht mehr lesbar zu schreiben, dies wäre
x1=x+h; d = (f(x1)-f(x))/(x1-x)
? ohne mit den flüchtigen.Eine Referenz, die ein compiler auslöschen können, die zweite Zeile der Funktion?
Nope, sorry. Je mehr ich darüber weiß, floating point, desto mehr glaube ich, dass der compiler ist nur erlaubt, es zu optimieren, wenn ausdrücklich dazu aufgefordert, mit
-ffast-math
oder gleichwertig.InformationsquelleAutor Alexandre C.
Gibt es zwei Verwendungen. Diese sind besonders Häufig in der embedded-Entwicklung.
Compiler nicht optimieren Sie die Funktionen, die die Variablen verwendet, die definiert sind mit volatile-Schlüsselwort
Volatile wird verwendet, um die genauen Speicherstellen im RAM, ROM, etc... Das ist öfter zu kontrollieren memory-mapped Geräte, Zugriff auf CPU-Register, und suchen Sie bestimmte Speicherbereiche.
Siehe Beispiel mit den assembly-listing.
Re: Verwendung von C - "volatile" - Schlüsselworts in der Embedded-Entwicklung
InformationsquelleAutor Neo Cambell
Flüchtige ist auch nützlich, wenn Sie erzwingen möchten, dass der compiler nicht optimieren, eine bestimmte code-Sequenz (z.B. für das schreiben eines micro-benchmark).
InformationsquelleAutor Diomidis Spinellis
Werde ich erwähnen, ein anderes Szenario, in dem flüchtige Bestandteile sind wichtig.
Angenommen, Sie Speicher-Karte eine Datei für die schnellere I/O und kann die Datei ändern, die hinter die kulissen (z.B. die Datei nicht auf Ihrer lokalen Festplatte, sondern bedient über das Netzwerk von einem anderen computer).
Wenn Sie den Zugriff auf die memory-mapped-Datei, die Daten über Zeiger auf nicht-volatile-Objekte (auf Quellcode-Ebene), dann wird der code vom compiler generiert abholen können die gleichen Daten mehrfach, ohne dass Sie sich dessen bewusst.
Wenn diese Daten passiert, zu ändern, Ihr Programm kann sich über zwei oder mehr verschiedene Versionen der Daten und bekommen in einem inkonsistenten Zustand. Dies kann dazu führen nicht nur zu logisch falschen Verhalten des Programms, sondern auch, um ausnutzbare Sicherheitslücken in der it, wenn es die Prozesse nicht vertrauenswürdigen Dateien oder Dateien von nicht vertrauenswürdigen Speicherorten.
Wenn Sie sich sorgen über die Sicherheit, und Sie sollten, dies ist ein wichtiges Szenario.
InformationsquelleAutor Alexey Frunze
volatile bedeutet, dass der Speicher wird sich wahrscheinlich ändern, und jederzeit geändert werden, aber etwas außerhalb der Kontrolle des anwenderprogramms. Dies bedeutet, dass, wenn Sie auf die variable verweisen, sollte das Programm immer überprüfen Sie die physische Adresse (also einem zugeordneten Eingabe-fifo), und nicht in einem Cache Weg.
InformationsquelleAutor Structure padding
Wiki sagen alles über
volatile
:Und die Linux-kernel-doc auch eine ausgezeichnete notation über
volatile
:InformationsquelleAutor coanor
Meiner Meinung nach, sollte man nicht zu viel erwarten von
volatile
. Um dies zu verdeutlichen, betrachten Sie das Beispiel in Nils Pipenbrinck hoch-stimmten Antwort.Ich würde sagen, sein Beispiel ist nicht geeignet für
volatile
.volatile
wird nur verwendet, um:verhindern, dass der compiler von nützlichen und wünschenswerten Optimierungen. Es ist nichts über die thread-sichere, atomic access oder auch Speicher um.
In diesem Beispiel:
den
gadget->data = data
vorgadget->command = command
nur ist nur gewährleistet, in kompilierter code, der vom compiler. Zur Zeit läuft der Prozessor noch eventuell verschiebt die Daten-und Befehls-Zuordnung, in Bezug auf die Prozessor-Architektur. Die hardware kann mit den falschen Daten(nehme gadget zugeordnet ist, die hardware-I/O). Die memory-Barriere muss zwischen Daten-und Befehls-Zuordnung.volatile
verschlechtern die Leistung ohne Grund. Als ob es ausreichend ist, das wird davon abhängen, dass andere Aspekte des Systems, die der Programmierer eventuell mehr wissen als der compiler. Auf der anderen Seite, wenn ein Prozessor, der garantiert, dass eine Anweisung zu schreiben, um eine bestimmte Adresse Spülen Sie die CPU-cache, aber ein compiler, sofern keine Möglichkeit zum flush-register-Cache-Variablen, die CPU weiß nichts über, das Spülen der cache nutzlos wäre.InformationsquelleAutor Oliver
Einen flüchtigen geändert werden kann von außerhalb der kompilierte code (zum Beispiel ein Programm kann anzeigen eine volatile-variable an eine memory-mapped-register.) Der compiler nicht gelten bestimmte Optimierungen auf code, der verarbeitet eine volatile-variable - zum Beispiel, wird es nicht laden Sie es in ein register schreiben ohne Sie in den Speicher. Dies ist wichtig beim Umgang mit hardware-Registern.
InformationsquelleAutor Ori Pessach
In der Sprache, entwickelt von Dennis Ritchie, jeden Zugriff auf jedes Objekt, andere als die automatische Objekte, deren Adresse nicht getroffen worden, würden die sich Verhalten, als wenn es berechnet die Adresse des Objekts, und dann gelesen oder geschrieben der Speicher an dieser Adresse. Dies machte die Sprache sehr mächtig, aber stark eingeschränkt Möglichkeiten zur Optimierung.
Während es vielleicht möglich gewesen, fügen Sie ein qualifier, die einladen würde zu einem compiler davon ausgehen, dass ein bestimmtes Objekt würde nicht geändert werden, in seltsame Wege, eine solche Annahme wäre für die überwiegende Mehrheit der Objekte in C-Programme, und es wäre unpraktisch, fügen Sie ein qualifier für alle Objekte, für die eine solche Annahme wäre angebracht. Auf der anderen Seite, einige Programme verwenden müssen einige Objekte, für die eine solche Annahme würde nicht halten. Um dieses Problem zu beheben, der Standard sagt, dass der Compiler kann davon ausgehen, dass Objekte, die nicht deklariert
volatile
wird nicht Ihren Wert beobachtet oder verändert in einer Weise, die außerhalb der compiler die Kontrolle, oder wäre außerhalb einer vernünftigen compiler Verständnis.Weil verschiedene Plattformen haben verschiedene Möglichkeiten, in denen die Objekte beobachtet werden oder geändert werden, die außerhalb eines compiler-Steuerung, es ist angemessen, die Qualität Compiler für diese Plattformen sollten sich in Ihrer genauen Umgang mit
volatile
Semantik. Leider, weil der Standard konnte nicht schlagen, die Qualität Compiler soll für low-level-Programmierung auf einer Plattform behandeln sollvolatile
in einer Weise, die erkennen und alle relevanten Auswirkungen einer bestimmten lese - /schreib-operation auf dieser Plattform, viele Compiler zu kurz, dies zu tun in einer Weise, die machen es schwieriger, Dinge zu verarbeiten wie hintergrund I/O in einer Weise, die effizient ist, aber nicht gebrochen werden können durch compiler - "Optimierungen".InformationsquelleAutor supercat
In einfachen Worten, es teilt dem compiler mit, dass Sie keine Optimierung auf eine bestimmte variable. Variablen, die zugeordnet sind, die Geräte-register geändert werden indirekt durch das Gerät. In diesem Fall, flüchtige verwendet werden muss.
InformationsquelleAutor rajeshsam
ist es nicht erlaubt-compiler zur automatischen ändern der Werte von Variablen. eine volatile-variable ist für den dynamischen Einsatz.
InformationsquelleAutor venu