Linux: Warum ist sig_atomic_t auf int typisiert?

Lesezeit: 7 Minuten

Benutzer-Avatar
smcdow

Auf meiner Linux-Box sig_atomic_t ist einfach alt int. Tun ints besitzt eine besondere atomare Qualität?

$ gcc -v
Using built-in specs.
Target: x86_64-linux-gnu
...
Thread model: posix
gcc version 4.3.2 (Debian 4.3.2-1.1) 

$ echo '#include <signal.h>' | gcc -E - | grep atomic
typedef int __sig_atomic_t;
typedef __sig_atomic_t sig_atomic_t;

  • @ Chrisaycock: C? Gilt dies nicht für jede Sprache mit Zugriff auf sig_atomic_t Variablen? Ich hätte es genauso gut benutzen können g++.

    – smcdow

    7. März 2012 um 18:55 Uhr


  • Das sig_atomic_t Typ ist eigentlich Teil der C-Spezifikation. Es ist auch in der C++-Spezifikation enthalten (wie die meisten Dinge), aber Sie erhalten am ehesten gute Antworten mit einem C-Tag.

    – Dietrich Ep

    7. März 2012 um 19:31 Uhr

  • C garantiert das nicht. Bestimmte CPUs haben bestimmte Garantien für die Atomarität bestimmter Typen. Insbesondere moderne CPUs, die in Desktop-Systemen verwendet werden, neigen dazu, Atomarität zumindest für Alignment zu garantieren ints (dh Daten in Wortgröße der Plattform). Dies ist nicht unbedingt der Fall für ältere CPUs oder für CPUs, die in eingebetteten Systemen verwendet werden.

    – ninjalj

    7. März 2012 um 19:59 Uhr

Benutzer-Avatar
zwöl

C99 sig_atomic_t entspricht nur einer sehr schwachen Definition von “Atomizität”, weil C99 hat kein Konzept der Parallelität, nur Unterbrechbarkeit. (C2011 fügt ein Nebenläufigkeitsmodell hinzu, und damit die _Atomic Typen, die stärkere Garantien geben; jedoch AFAIK sig_atomic_t ist unverändert, da seine Daseinsberechtigung ist immer noch die Kommunikation mit Signalhandlern, nicht über Threads hinweg.)

Das ist alles, worüber C99 sagt sig_atomic_t:

(§7.14 <signal.h>Absatz 2) Der definierte Typ ist sig_atomic_t, das ist der (möglicherweise flüchtig qualifizierte) ganzzahlige Typ eines Objekts, auf das als atomare Entität zugegriffen werden kann, selbst bei Vorhandensein von asynchronen Interrupts. (§7.14 <signal.h>Absatz 2)

(§7.14p5) Wenn [a] Signal tritt anders als als Ergebnis des Aufrufs von auf abort oder raise -Funktion ist das Verhalten undefiniert, wenn der Signal-Handler auf ein beliebiges Objekt mit statischer Speicherdauer verweist, außer durch Zuweisen eines Werts zu einem als deklarierten Objekt volatile sig_atomic_t.

(§7.18.3 Grenzwerte anderer Integer-Typen, Absatz 3) Wenn sig_atomic_t (siehe 7.14) ist als vorzeichenbehafteter Integer-Typ definiert, der Wert von SIG_ATOMIC_MIN darf nicht größer als −127 und der Wert von sein SIG_ATOMIC_MAX darf nicht weniger als 127 sein; andernfalls ist sig_atomic_t als vorzeichenloser ganzzahliger Typ und der Wert von definiert SIG_ATOMIC_MIN soll 0 und der Wert von sein SIG_ATOMIC_MAX darf nicht weniger als 255 betragen.

Der Begriff “atomare Entität” ist nirgendwo im Standard definiert. Übersetzen von Standards-esisch, die Absicht ist, dass die CPU eine Variable vom Typ vollständig aktualisieren kann sig_atomic_t im Speicher (“statische Speicherdauer”) mit einem Maschinenbefehl. Daher ist es in der parallelitätsfreien, präzise unterbrechbaren abstrakten C99-Maschine für einen Signalhandler unmöglich, eine Typvariable zu beobachten sig_atomic_t Mitten in einem Update. Die §7.18.3p3-Sprachlizenzen für diesen Typ sind so klein wie möglich char im Bedarfsfall. Beachten Sie bitte die völlige Abwesenheit jeder Sprache in Bezug auf prozessorübergreifende Konsistenz.

Es gibt echte CPUs, die mehr als eine Anweisung benötigen, um einen Wert größer als zu schreiben char zur Erinnerung. Es gibt auch echte CPUs, die mehr als einen Befehl benötigen, um Werte zu schreiben kleiner als ein Maschinenwort (oft, aber nicht notwendigerweise dasselbe wie int) in Erinnerung. Die Sprache im Handbuch der GNU C-Bibliothek ist jetzt ungenau. Es stellt den Wunsch der ursprünglichen Autoren dar, das zu eliminieren, was sie als unnötige Lizenz für C-Implementierungen betrachteten, um seltsamen Scheiß zu tun, der Anwendungsprogrammierern das Leben schwerer machte. Unglücklicherweise ist es genau diese Lizenz, die es möglich macht, C auf einigen echten Maschinen überhaupt zu haben. Es gibt mindestens einen Embedded-Linux-Port (zum AVR), für den beides nicht der Fall ist int noch Zeiger können in einem Befehl in den Speicher geschrieben werden. (Es wird daran gearbeitet, das Handbuch genauer zu machen, siehe zB http://sourceware.org/ml/libc-alpha/2012-02/msg00651.htmlsig_atomic_t scheint jedoch in diesem übersehen worden zu sein.)

  • Heh, sieht aus wie nicht. Es wäre wahrscheinlich besser dran mit etwas Kleinerem 🙂 Ich neige jedoch zu der Meinung, dass Linux/AVR mit welcher C-Bibliothek heutzutage eher ein relevantes Portabilitätsziel ist als Hurd oder andere Boutique-aber-nicht-eingebettete Betriebssysteme.

    – zol

    7. März 2012 um 20:12 Uhr


  • Ok, dann gehe ich davon aus, dass das glibc-Handbuch nicht ungenau ist. (Beachten Sie, dass es heißt: In der Praxis und diese gelten auf allen Maschinen, die die GNU-C-Bibliothek unterstützt)

    – ninjalj

    7. März 2012 um 20:18 Uhr

  • Beachten Sie, dass sig_atomic_t tut nichts, um Read-Modify-Write-Operationen in Bezug auf Signale atomar zu machen. Auf x86 können Interrupts nicht aufgeteilt werden dec dword [mem], also ist es in einem Uniprozessor-Kernel in Bezug auf Interrupts oder ein Single-Threaded-Prozess in Bezug auf Signale atomar 2. Hälfte dieser Antwort. Aber (AFAIK) es gibt keine ISO- oder GNU C11-Möglichkeit, dies anzufordern num-- kompiliert dazu anstelle von separaten Lade-/Speicher-Insns, ohne ein Atomic zu verwenden, das kompiliert wird lock dec dword [num]. Inline asm natürlich nicht mitgezählt.

    – Peter Cordes

    9. September 2016 um 17:14 Uhr

  • Nur um konkret zu den Einschränkungen zu sein: Sie erhalten auch keine Kontrolle über die Neuordnung zur Kompilierzeit, und der Compiler geht davon aus, dass das Objekt nicht asynchron geändert wird. (So while(updated_by_sig_handler == 0){} kompilieren kann if(update_by_sig_handler == 0){ while(true); } anstelle einer Schleife, die den Speicher innerhalb der Schleife erneut liest, bis sie einen Wert sieht, der von einem Signalhandler geschrieben wurde. Oder heben Sie die Last aus einer Schleife, die während des Wartens etwas tut. Das Schreiben von Spin-Loops selbst ist fast immer schlecht, selbst wenn Sie C11-Atomics verwenden, aber es ist ein einfaches Beispiel.)

    – Peter Cordes

    9. September 2016 um 17:22 Uhr

  • Oh richtig, ich habe diese Sprache im Standard gesehen, aber ich habe nicht aufgehört, mich darum zu kümmern. Und das muss natürlich sein volatile, derp, die die asynchrone Modifikationsannahme auslöst. Danke für die Erklärung, ich verstehe jetzt, was diese juristische Sprache sagt. Interessanter Punkt, dass die _Atomic muss schlossfrei sein. Da es sich um einen Signalhandler im selben Thread handelt, würde es einen potenziellen Deadlock erzeugen, wenn der Signalhandler versuchen würde, eine Sperre zu erwerben, die der Thread manchmal hält.

    – Peter Cordes

    9. September 2016 um 19:19 Uhr

Bestimmte Typen können mehrere Anweisungen zum Lesen/Schreiben erfordern. int Typ wird immer atomar gelesen/geschrieben.

Datentyp: sig_atomic_t

Dies ist ein ganzzahliger Datentyp. Auf Objekte dieses Typs wird immer atomar zugegriffen.

In der Praxis können Sie davon ausgehen, dass int und andere Integer-Typen nicht länger als int atomar sind. Sie können auch davon ausgehen, dass Zeigertypen atomar sind; das ist sehr bequem. Beides gilt für alle Maschinen, die von der GNU-C-Bibliothek unterstützt werden, und für alle uns bekannten POSIX-Systeme.

Bezug

  • Es ist normalerweise der Fall, dass int wird immer atomar gelesen und geschrieben. Der C-Standard garantiert dies nicht ausdrücklich. Die Umsetzung durch Definition sig_atomic_t wie intverspricht, dass dem so ist für diese Umsetzung. Sie sollten nicht davon ausgehen, dass dies für alle Implementierungen gilt.

    – Keith Thompson

    7. März 2012 um 18:40 Uhr

  • Eine aktuellere Hinweis. Nur zur Verdeutlichung, dies gilt nur für die GNU C-Bibliothek? Mit oder ohne GCC? Ich habe noch nie von einem einfachen Typ gehört, der in Standard-C atomaren Zugriff hat (mit Ausnahme normaler atomarer Methoden und Sperrmechanismen).

    – Ian

    7. März 2012 um 18:42 Uhr


  • @Ioan C99 hat kein Parallelitätsmodell, was also mit “atomar” gemeint ist, ist etwas sehr Schwaches im Vergleich zu dem, woran Sie wahrscheinlich denken. Siehe meine Antwort.

    – zol

    7. März 2012 um 19:28 Uhr

1371310cookie-checkLinux: Warum ist sig_atomic_t auf int typisiert?

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

Privacy policy